浏览器解析
我们平常上传文件(图片、音频、视频等)到oss上,如果想要直接在浏览器下载,需要区分如下情况
1、ppt、excel表格,不能直接被浏览器解析
2、图片、mp4,可以直接被浏览器解析并打开
文件下载方法
a标签下载
a标签有一个download属性,规定被下载的超链接目标,可以给下载文件命名,所允许的值没有限制,浏览器将自动检测正确的文件扩展名并添加到文件 (.img, .pdf, .txt, .html, 等等),href是文件的地址,如下:
Download() {
let aLabel = document.createElement('a'); //创建a标签
aLabel.href = '';
aLabel.download = 'mp4';
aLabel.click();
}
如果是下载多个,可以循环调用这个方法,记得每一个都进行一定时间的延迟,否则可能会下载失败,后面下载的可能会被取消,或者是只下载了最后一个
二进制文件流下载
二进制流文件,需要从后台接口中拿到这些二进制数据,然后使用URL.createObjectURL生成一个可以使用的url,然后赋值给a链接的href属性,后续操作和上一操作一样,但是这种方式适合文件比较小的情况,如果是视频那种大文件,不建议
this.$axios({
method: "post", //请求方式
responseType: "blob", //告诉服务器我们需要的响应格式
url: "fileService/fileService/download", //地址
data: {
fileId: item.fileId,
authorId: window.localStorage.getItem("authorId")
}
}).then(res => {
let url = window.URL.createObjectURL(new Blob([res.data])); //转换为可用URl地址
let link = document.createElement("a"); //创建a标签
link.style.display = "none"; //使之不可见
link.href = url; //赋URL地址
link.setAttribute("download", item.fileName); //设置下载属性、以及文件名
document.body.appendChild(link); //将a标签插至页面中
link.click(); //强制触发a标签事件
});
iframe下载
iframe也是可以进行下载的
var iframe = document.createElement("iframe");
iframe.src = "GenerateFile.aspx?filepath=" + filepath;
iframe.style.display = "none";
document.body.appendChild(iframe);
form表单提交下载
模拟form表单提交
var form=$("");
form.attr("style","display:none");
form.attr("target","");
form.attr("method","get");
form.attr("action",url);
$("body").append(form);
form.submit();//表单提交
综上,使用最多的就是a标签下载,但是a标签下载需要注意:
1、同源下,如果是浏览器不能自动解析的文件,直接使用href就可以下载
2、同源下,如果是类似png格式的,就需要添加download属性
3、不同源下,download属性就失效了
4、download失效后,比如说mp4文件,使用a标签打开,会直接在浏览器播放这个视频,所以我们要做的是,要么修改成同源(后台设置、前端设置代理),要么修改响应头
‘Content-Disposition’: ‘attachment;filename=’
content-disposition 一般有两种方式: inline:直接在页面显示 attchment:以附件形式下载 |
---|
字段说明:
Content-Disposition为属性名,disposition-type是以什么方式下载,如attachment为以附件方式下载disposition-parm为默认保存时的文件名服务端向客户端游览器发送文件时,如果是浏览器支持的文件类型,一般会默认使用浏览器打开,比如txt、jpg等,会直接在浏览器中显示,如果需要提示用户保存,就要利用Content-Disposition进行一下处理,关键在于一定要加上attachment,后面跟的filename是下载文件的文件名称
当然filename参数可以包含路径信息,但User-Agnet会忽略掉这些信息,只会把路径信息的最后一部分做为文件名。
注意事项:
当代码里面使用Content-Disposition来确保浏览器弹出下载对话框的时候。 response.addHeader(“Content-Disposition”,”attachment”);一定要确保没有做过关于禁止浏览器缓存的操作。
不然会发现下载功能在opera和firefox里面好好的没问题,在IE下面就是不行。
关于OSS
目前我测试,如果使用oss的putObject上传方式,我们可以手动新增请求头,’Content-Disposition’: ‘attachment;filename=’,然后在浏览器打开的时候,响应头也会加上这个,所以浏览器就可以直接下载了
response-content-type=application/octet-stream
这种方式也可以直接从浏览器下载,它以流的形式下载文件,这样可以实现任意格式的文件下载,如果响应头content-type设置为这个,则浏览器可以自己进行下载
我们现在使用postObject方式,这种方式是不支持设置content-disposition的,但是可以在url上拼接response-content-type=application/octet-stream为参数,前提参数是需要计算到签名中的,我们这种上传方式是后台给我们id,然后把key和另外一些配置计算到签名中返回给我们的
我测试了这两种可以可以在跨域的情况下,用a标签,通过设置download属性进行下载,而不是预览