关闭

图片下载的几种实现

时间: 2020-02-07阅读: 466标签: 图片

下载图片的几种方式

通过浏览器自动下载。浏览器接收到二进制文件,自动转码下载。比如: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、如果没设置响应头,又跨域,那只能使用服务器代理
站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

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

关闭

前端开发中对图片的优化技巧有哪些?

除了内容图片,其他的图片的作用是修饰,也就是对于传达信息来说并非本质性的。最大的优化就是压根不要图片!所以在优化之前要做的,首先是确认设计,设计本身是否需要用那么多图片?还是说可以更简洁?

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

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

node之本地服务器图片上传

对于接口文件的返回,这里使用了body-parser这个中间件来对node返回的body进行json格式的解析,很重要的一点就是设置静态资源目录,不然的话就会报错,找不到文件或者文件夹

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

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

HTML img src图片路径不存在,则显示一张默认图片的方法

我们一般会给图片设置 alt 属性,当图片路径不存在时可以显示提示文字。但是这样很不好看,如果用在文章列表,我们可以给 img 标签设置一个 onerror 属性,可以在 src 路径不存在时显示指定的默认图片

html2canvas保存图片模糊问题解决

使用官网的CDN,网上可以查到很多解决方案,常用的主要就是:canvas先放大,其次加个dpi效果也可以,代码如下:

vue使用readAsDataURL实现选择图片文件后预览

方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成DONE,并触发 loadend 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容

谈谈 Web 图片浏览体验与优化

图片,在一张网页上起到了相当大的作用。一个充满艺术的网站,它们的排版往往十分简洁、大方,整张网页的美感全体现在了一张背景图和产品图=== 而在浏览这样的网页时,其响应速度决定了用户体验。如果你正在打开一个自己比较感兴趣的网站

图片格式区别:png8,png24,jpg,jpeg,gif,webp

色彩丰富的、比较大的图片切成jpg格式,例如一些网站的banner图,WEBP因为体积小,正在被大量网站使用。网站加速的内容一半包含了WEBP这种格式,但是写代码必须考虑部分不支持webp,比如苹果系统的Safari浏览器就不支持。

手机横屏和竖屏情况下的图片旋转

图片渲染要解决的几个主要问题:1、图片默认是水平方向,要设置图片居中2、需要旋转的情况是:图片的宽度大于高度,这样旋转后图片显示的就大些3、在旋转之前要确认好图片的大小,因为旋转后依然是以旋转前的图片的大小

点击更多...

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