a标签跨域下载

以前项目中的一个文件上传后下载的需求,后端是把文件存在文件服务器,而后返回给前端一个文件地址
拿到url后使用a标签下载,可是对于文件是图片,.txt或者 .pdf这些浏览器能够直接打开的文件,没有下载,而是直接在当前页面打开了,缘由是由于url不是同源的 前端

MDN
MDN中说a标签的download的属性仅适用于同源URLs,可是它又说能够使用 blob:URLsdata:URLs的形式

1. 下面是使用blob:URLsdata:URLs来下载图片的代码

//  data: URLs方式
downloadByData (url) {
  let image = new Image()
  image.setAttribute('crossOrigin', 'anonymous')
  image.src = url
  image.onload = () => {
    let canvas = document.createElement('canvas')
    canvas.width = image.width
    canvas.height = image.height
    let ctx = canvas.getContext('2d')
    ctx.drawImage(image, 0, 0, image.width, image.height)
    let ext = image.src.substring(image.src.lastIndexOf('.')+1).toLowerCase()
    let dataURL = canvas.toDataURL('image/' + ext)
    download(dataURL)
  }
},
//  blob: URLs方式
downloadByBlob (url) {
  let image = new Image()
  image.setAttribute('crossOrigin', 'anonymous')
  image.src = url
  image.onload = () => {
    let canvas = document.createElement('canvas')
    canvas.width = image.width
    canvas.height = image.height
    let ctx = canvas.getContext('2d')
    ctx.drawImage(image, 0, 0, image.width, image.height)
    canvas.toBlob((blob) => {
      let url = URL.createObjectURL(blob)
      download(url)
      // 用完释放URL对象
      URL.revokeObjectURL(url)
    })
  }
},
download (href, name = 'pic') {
  let eleLink = document.createElement('a')
  eleLink.download = name
  eleLink.href = href
  eleLink.click()
  eleLink.remove()
}
复制代码

data: URLs方式是先建立一个图片,而后用canvas绘制该图片,而后使用canvas.toDataURL得到Data URLs
blob: URLs方式也差很少,使用canvas.toBlob获得blob,而后使用URL.createObjectURL建立URL对象
代码中有设置图片的crossOrigin属性image.setAttribute('crossOrigin', 'anonymous'),由于图片跨域,canvas的toDataURL和toBlob都会报错拿不到结果ios

因此须要设置crossOrigin,具体解释能够看一下张鑫旭大佬的这篇文章 《解决canvas图片getImageData,toDataURL跨域问题》

可是上面的方法对于txt和pdf文件就不行了nginx

2. 从服务器get文件的blob数据

直接经过ajax请求,get到文件的blob数据,而后使用blob:URLs的形式下载ajax

downloadByGetBlob (url) {
  axios.get(url, {responseType: 'blob'}).then(res => {
    let blob = res.data
    let url = URL.createObjectURL(blob)
    download(url)
    // 用完释放URL对象
    URL.revokeObjectURL(url)
  })
}
复制代码

这种方式须要注意跨域问题,须要后端服务器支持canvas

3. 另外,也能够经过配置nginx反向代理

location /images {
  proxy_redirect  off;
  proxy_pass  https://www.yourfile.com;
}
复制代码
相关文章
相关标签/搜索