图片下载的几种实现

更新日期: 2020-02-07阅读: 1.9k标签: 图片

下载图片的几种方式

通过浏览器自动下载。浏览器接收到二进制文件,自动转码下载。比如:window.open()

通过xhr下载。ajax请求得到的是二进制文件,只能手动转码下载。


第一种:浏览器自动下载型

这种需要后端配置响应参数

window.open

例子:
本地起了一个node服务,端口3000

设置了content-disposition的情况:

页面设置:

<button onclick="downImg(1)">点击下载图片</button>
<button onclick="downImg(2)">点击下载excel</button>
<script>
    function downImg(type) {
        if(type ===1) {
            window.open('http://127.0.0.1:3000/img');
        } else {
            window.open('http://127.0.0.1:3000/api');
        }
    }
</script>

后端:

app.get('/img', (req, res) => {
    res.setHeader('Content-Type', 'image/jpeg');
    // res.download自动设置Content-disposition
    res.download('./public/1.jpg'); 
})

实验结果:

ie >=8 ,成功下载图片;

chrome,成功下载图片;

未设置content-disposition的情况

app.get('/img', (req, res) => {
    res.setHeader('Content-Type', 'image/jpeg');
    let pathname = path.join(__dirname, './public/1.jpg')
    res.sendFile(pathname);
})
app.get('/api', (req, res) => {
    res.setHeader('Content-Type', 'application/vnd.ms-excel');
    let pathname = path.join(__dirname, './public/api.xlsx')
    res.sendFile(pathname);
})

实验结果:

图片在新标签页打开

excel表自动下载了

通过a标签请求
function alabel(src, downloadName) {
    // 注意,ie11还不支持es6的语法
    var a = document.createElement('a');
    a.target = "_blank";
    a.href = src;
    a.download = downloadName;
    a.click();
}
function downImg() {
    var url = 'http://127.0.0.1:3000/img';
    alabel(url, '1.jpg');
}

实验结果:

浏览器chromeie
同域可以下载不能下载
跨域打开新标签页不能下载
设置content-disposition可以下载不能下载
没设置content-disposition可以下载不能下载

所以a标签下载跟浏览器的兼容性和是否跨域有关

第一种情况结论
1、对于图片下载,需要设置响应头:`content-disposition`,该字段的作用是告诉浏览器,这是一个附件;对于excel表格,不管是否设置了响应头,都会下载。
2、window.open()没有跨域问题,没有浏览器兼容性问题
3、相对于a标签,window.open会好一些,a标签有浏览器的兼容性问题。


第二种:通过xhr转换

通过xhr转换的有多种
blob下载

blob下载必须设置responseType:blob,否则返回的是一堆乱码的字符串。设置responseType:blob之后,浏览器将返回数据转成blob对象。

首先,创建xhr对象,请求接口
接下来是常见的浏览器网络请求接口4步骤:

createXHR(url, data, method, successCallBack, errCallBack) {
    // 创建xhr对象
    let xhr = new XMLHttpRequest();
    // 连接
    xhr.open(method, url);
    // 发送
    xhr.send(data);
    // 必须设置responseType,否则返回的是字符串
    xhr.responseType = "blob";
    xhr.onreadystatechange = function() {
        // xhr的请求状态有0,1,2,3,4
        if(xhr.readyState === 4) {
            // 返回的状态码
            if(xhr.status === 200) {
                // Content-Disposition获取文件名
                successCallBack(xhr.response, xhr.getResponseHeader("Content-Disposition"));
            } else {
                errCallBack(xhr.response);
            }
        }
    }
}

调用createXHR

var url = 'http://127.0.0.1:3000/img';
createXHR(url, {},'GET', function(res, header) {
    let downloadName = header.split('filename="')[1].slice(0, -1);
    blob([res], 'image/jpeg', downloadName)
}, function(e) {
    console.log(e);  
})

blob方法

blob(data, content_type, downloadName) {
    let blob = new Blob(data, { type: content_type});
    // URL.createObjectURL生成一个domString, 包含了一个url对象,这个url对象与file对象或者blob对象有一个映射关系。 URL 的生命周期和创建它的窗口中的 document 绑定
    let url = URL.createObjectURL(blob);
    alabel(url, downloadName);
    // 销毁url, 回收内存
    URL.revokeObjectURL(url);
}

可以使用blob构造函数,那也可以使用h5的fileReader, 因为fileReader继承blob。fileReader的写法如下:

// FileReader转换对象不需要数组形式,blob是数组格式
fileReader(res, '1.jpg');

fileReader(data, downloadName) {
    let reader = new FileReader();
    reader.readAsDataURL(data);
    reader.addEventListener('load', function() {
        alabel(this.result, downloadName);
    })
}

实验结果:

blob下载,使用的是Blob构造函数。最后还是要创建a标签下载。我们也知道a标签下载的一些缺点,同样blob下载也存在这样的缺点。

getResponseHeader,如果是跨域,只能获取到Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma几个响应头,如果需要获取其他的响应头,需要设置Access-Control-Expose-Headers

兼容ie下载文件

a标签下载有浏览器兼容问题。要兼容ie就要找其他的方法。前面有提到的window.open,还有一种是iframe

iframe标签

var url = 'http://127.0.0.1:3000/img';
var iframe = document.createElement("iframe");  
iframe.src = url;  
iframe.style.display = "none";  
document.body.appendChild(iframe);
iframe.click();

实验结果:

兼容性:ie,chrome

但是要设置content-disposition

还有一种ie自有的下载文件,ie10以上

window.navigator.msSaveBlob(blob, '1.jpg');
跨域,没设置响应头,又要兼容ie

这种情况只能说是作死,但是没办法,实际情况也有可能有这么样。这种情况呢,只能是使用服务端做代理。这里使用的是node做代理。

页面:

// url是目标图片地址, serverApi是本地服务器接口
var url = 'http://http://127.0.0.1:3001/img';
var serverApi = 'http://127.0.0.1:3000/download'
createXHR(serverApi, {url},'POST', function(res, header) {
        blob(res, 'image/jpeg','1.jpg');
    }, function(e) {/*  */
        console.log(e);    
    })

服务端:

app.post('/download', (req, res) => {
    res.setHeader('Content-Type', 'image/png')
    request.get(req.body.url).pipe(res)
})


最后

1、如果响应头设置有content-disposition,可以使用window.open

2、不满足1时,可以使用a标签下载

3、如果要兼容ie,可以使用navigator.msSaveBlob

4、如果没设置响应头,又跨域,那只能使用服务器代理

链接: https://www.fly63.com/article/detial/8516

原生Js对文件类型的判断,判断文件是图片,视频等格式

在我们开发中,会遇到这样的场景:1.服务器返回Json数据,根据数据类型来显示是图片还是视频。2.前端上传文件,需要指定文件类型才能上传到服务器。这时候就需要使用Js来判断对应文件的类型

前端图片懒加载的实现,采用Lazy Load 图片延迟加载提高用户体验

对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。这样子对于页面加载性能上会有很大的提升,也提高了用户体验。

web前端图片加载优化,从图片模糊到清晰的实现过程

在网页图片显示的时候,会发现许多网站采用了先模糊,然后在慢慢清晰的过程,这样的加载用户体验是比较好的,那么如何实现呐?默认加载2张图片,一张缩略图,一张原图,当打开网页的时候默认只显示缩略图

lazysizes.js使用方法_实现图片懒加载、延迟加载的js插件

当你的网站使用了大量图片时候,如果一次性全部加载,那么会严重影响网站的速度。通过lazysizes.js插件就能很好解决这个问题,它可以实现图片的延迟加载【懒加载】

js实现图片局部放大效果

图片局部放大效果结合的知识点主要是DOM的操作,以及事件的应用,所以首先要对DOM的操作有一定了解,其次能对事件的应用有一定的累积。

网站图片优化的重要性与技巧方案

网站图片优化技巧:1、图片名包括关键词,2、Alt标签包括关键词,3、图片周边文本包括关键词,4、GLF和JPGE图画优化,5、在图片链接中运用锚文本关键字

css实现不定宽高的图片img居中裁剪_类似微信朋友圈图片效果

前端需要显示矩形的缩略图,接口返回的图片尺寸大小不一,宽高不相等,需要前端来处理并显示成正方形,类似微信朋友圈图片的效果。那么使用纯css该如何实现不定宽高的图片居中裁剪呢?

原生js 生成海报图_利用canvas合成图片的实现方法

目前浏览器对html5的支持越来越好,我们现在不用服务器端,直接在前端利用canvas就可以进行图片的合成了。下面就介绍下如何通过原生js 来生成海报图

网页中默认图片的几种解决方式

现在网页中图片随处可见,但避免不了有时会出现图片资源失败的情况,这里的alt属性是为了当图片加载失败时告诉用户图片信息的 ,能不能美化一下呢?下面给出几种方式

h5移动端禁止长按图片保存

在移动端访问H5页面的时候,长按图片就会把图片保存起来,为了能够让用户体验更好一些,我们需要长按的时候也不保存图片。那该如何实现呢?下面给出3种解决方案。使用 pointer-events:none、全局属性、加一层遮罩层

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!