今天在前端工匠的群里,看到了一个问题(下载文件,但是请求头中需要传递 token,如何下载文件?怎么设置文件类型?),我们来解决一下这个问题。
下载文件方案
- (服务端)设置下载头
Content-disposition
。兼容性好。Content-disposition: attachment
Content-Disposition: attachment; filename=abc.txt
(前端)特性触发下载。移动端基本可以放弃,PC 端别考虑低版本 IE。
- dataurl,base64 设置下载头
- a 标签的 download 属性
如何处理鉴权相关逻辑?
- cookie。从 cookie 获取用户登录信息,然后判断是否有下载资源的权限。
普普通通的方案。 - headers。从 headers 获取用户登录信息,然后判断是否有下载资源的权限。
这种一般是 cookie 的升级,一般是一些防护 CSRF (跨站请求伪造)的系统架构。
但是浏览器默认请求时无法使用,比如location.href
等方式。 - url。从 url 获取权限信息,然后判断。
感觉是最好的方案,比如说给一个key,有效期为五分钟,获取资源的时候直接判断。
和账号系统独立开,可以把资源放在第三方的系统。
浏览器 | ajax | |
---|---|---|
cookie | 可以设置 | 可以设置 |
header | 不可以设置 | 可以设置 |
url | 可以设置 | 可以设置 |
因为他们的系统架构必须传递 header,所以只能用 ajax 这些浏览器下载方案了。
前端 ajax 下载文件
- 通过
ajax
请求资源 - 资源转换为
blob
URL.createObjectURL(blob);
获取 bloburl- 使用
download
属性,然后通过click
触发下载。
function downloadFile(blob, fileName, ext){
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = (fileName || Date.now()) + (ext?`.${ext}`:'');
document.body.appendChild(a);
a.click();
document.body.removeChild(a);// 兼容火狐
}
urls = [
'//www.lilnong.top/static/html/_template.html',
'//www.lilnong.top/static/css/normalize-8.0.0.css',
'//www.lilnong.top/static/img/20190515/index-cir4.png',
'//www.lilnong.top/static/fontmin/5d1e8557b8e311dae9ff17ee45563a27.svg',
'//www.lilnong.top/static/fontmin/52ea7c14fd3e6a77587a50d251b0438a.ttf',
'//www.lilnong.top/static/json/sitemap.json',
'//www.lilnong.top/static/pdf/2018-ebook-engineer.pdf',
'//www.lilnong.top/static/video/friday.mp4',
'//www.lilnong.top/download/html/_template.html',
'//www.lilnong.top/download/css/normalize-8.0.0.css',
'//www.lilnong.top/download/img/20190515/index-cir4.png',
'//www.lilnong.top/download/fontmin/5d1e8557b8e311dae9ff17ee45563a27.svg',
'//www.lilnong.top/download/fontmin/52ea7c14fd3e6a77587a50d251b0438a.ttf',
'//www.lilnong.top/download/json/sitemap.json',
'//www.lilnong.top/download/pdf/2018-ebook-engineer.pdf',
'//www.lilnong.top/download/video/friday.mp4'
]
urls.forEach(url=>{
var xhr = new XMLHttpRequest();
xhr.open('get', url)
xhr.responseType = 'blob'
xhr.send()
xhr.onload = function(){
downloadFile(xhr.response, '1'+ url)
}
})
function downloadFile(blob, fileName, ext){
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = (fileName || Date.now()) + (ext?`.${ext}`:'');
document.body.appendChild(a);
a.click();
document.body.removeChild(a);// 兼容火狐
}
获取 ajax 下载的文件类型
urls = [
'//www.lilnong.top/static/html/_template.html',
'//www.lilnong.top/static/css/normalize-8.0.0.css',
'//www.lilnong.top/static/img/20190515/index-cir4.png',
'//www.lilnong.top/static/fontmin/5d1e8557b8e311dae9ff17ee45563a27.svg',
'//www.lilnong.top/static/fontmin/52ea7c14fd3e6a77587a50d251b0438a.ttf',
'//www.lilnong.top/static/json/sitemap.json',
'//www.lilnong.top/static/pdf/2018-ebook-engineer.pdf',
'//www.lilnong.top/static/video/friday.mp4',
'//www.lilnong.top/download/html/_template.html',
'//www.lilnong.top/download/css/normalize-8.0.0.css',
'//www.lilnong.top/download/img/20190515/index-cir4.png',
'//www.lilnong.top/download/fontmin/5d1e8557b8e311dae9ff17ee45563a27.svg',
'//www.lilnong.top/download/fontmin/52ea7c14fd3e6a77587a50d251b0438a.ttf',
'//www.lilnong.top/download/json/sitemap.json',
'//www.lilnong.top/download/pdf/2018-ebook-engineer.pdf',
'//www.lilnong.top/download/video/friday.mp4'
]
urls.forEach(url=>{
var xhr = new XMLHttpRequest();
xhr.open('get', url)
xhr.responseType = 'blob'
xhr.send()
xhr.onload = function(){
// console.log(url, xhr.response, xhr);
console.log(url, xhr.response);
}
})
可以看到,我们设置 responseType = 'blob'
直接就可以通过 type 获取文件类型
通过解析 response 响应头获取类型
从 http 的响应头来分析,我们有两个地方可以获取。
- 通过
content-type
来获取 - 通过
Content-Disposition
来获取
urls = [
'//www.lilnong.top/static/html/_template.html',
'//www.lilnong.top/static/css/normalize-8.0.0.css',
'//www.lilnong.top/static/img/20190515/index-cir4.png',
'//www.lilnong.top/static/fontmin/5d1e8557b8e311dae9ff17ee45563a27.svg',
'//www.lilnong.top/static/fontmin/52ea7c14fd3e6a77587a50d251b0438a.ttf',
'//www.lilnong.top/static/json/sitemap.json',
'//www.lilnong.top/static/pdf/2018-ebook-engineer.pdf',
'//www.lilnong.top/static/video/friday.mp4',
'//www.lilnong.top/download/html/_template.html',
'//www.lilnong.top/download/css/normalize-8.0.0.css',
'//www.lilnong.top/download/img/20190515/index-cir4.png',
'//www.lilnong.top/download/fontmin/5d1e8557b8e311dae9ff17ee45563a27.svg',
'//www.lilnong.top/download/fontmin/52ea7c14fd3e6a77587a50d251b0438a.ttf',
'//www.lilnong.top/download/json/sitemap.json',
'//www.lilnong.top/download/pdf/2018-ebook-engineer.pdf',
'//www.lilnong.top/download/video/friday.mp4'
]
urls.forEach(url=>{
var xhr = new XMLHttpRequest();
xhr.open('get', url)
xhr.responseType = 'blob'
xhr.send()
xhr.onload = function(){
console.log(url, xhr.getAllResponseHeaders().match(/content-type: ([\w/]+)/g))
}
})
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。