Skip to content Skip to sidebar Skip to footer

前端如何通过链接去下载img图片

很多项目中都有下载一些图片文件的需求,常用的方式是通过a标签实现:

<a href="download.jpg"></a>
复制代码

但是你会在使用时发现点击该链接后并不是下载对应的图片,而是在浏览器中打开了对应的图片,这并不是我们想要的。

应为浏览器判断是否下载一般会根据文件返回的头信息进行判断,如果给返回了对应的头信息则会进行下载:

header('Content-type: image/jpeg'); 
header("Content-Disposition: attachment; filename='download.jpg'"); 
复制代码

很好,但是如果这样还需要后端人员的配合,我们有没有其他的方式呢?有,那就是使用download属性:

<a href="download.jpg" download>下载</a>
复制代码

这样就可以直接调用浏览器的下载功能,而且还可以通过传参给download来实现文件的重命名功能:

<a href="download.jpg" download="othername.jpg">下载</a>
复制代码

download属性的兼容性如下:

caniuse.com/download/em…

但是这个方案依然有他的问题:

chrome 69.0.3497.92 中已经严格遵循同源策略的限制,如果加载了非同源的内容,download 属性将失效,等效导航功能。

现在很多项目已经是前后端分离,经常遇到跨域的问题,但是在跨域的情况下download属性完全没有作用,那么应该如何解决。

基本的思路就是让跨域变成不是跨域。


一种思路就是通过反向代理进行处理,来解决跨域问题:

1.将原先访问图片云服务的资源改为访问网站图片资源,例如:

  <a href="http://prod.upaiyun.com/images/xxx.jpg" download="xxx.jpg">download</a>
  改为:
  <a href="http://www.mysite.com/images/xxx.jpg" download="xxx.jpg">download</a>
复制代码

2.配置nginx反向代理

  location /images {
    proxy_redirect    off;
    proxy_pass https://prod.upaiyun.com;
  }
复制代码

另一种方式就是,创建一个非跨域的数据源:

1.下载原数据文件,这里可以使用img标签或者通过ajax,fetch进行下载

   function download(url, name) {
        name = name || url
        // fetch抓取图片数据
        fetch(url).then(response=> {
            if( response.status == 200 )
                // 返回的.blob()为promise,然后生成了blob对象,此方法获得的blob对象包含了数据类型,十分方便
                return response.blob()
            throw new Error(`status: ${response.status}.`)
        }).then(blob=> {
            // 获取到blob对象
            downloadFile(name, blob)
        }).catch(error=> {
            console.log("failed. cause:", error)
        })
    }
复制代码

2.通过URL.createObjectURL给a标签设置数据源

function downloadFile(fileName, blob) {
       const anchor = document.getElementById("a")
       // 创建指向blob对象地址
       const src = URL.createObjectURL(blob)
       anchor.download = fileName
       anchor.href = src
}
复制代码

这样就可以实现在跨域情况下的图片资源的下载。 当然还有一下其他类似的方案如使用FileReaderreadAsDataURL来生成数据,或使用CanvastoDataUrl都可以达到一样的效果。

作者:紫菜苔同学
链接:https://juejin.im/post/5caef3a7e51d456e5633ddbc

Leave a comment