如何通过 response 的头信息获取文件类型?


思否
HTTP JavaScript

转载自 SegmentFault

今天在前端工匠的群里,看到了一个问题(下载文件,但是请求头中需要传递 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,有效期为五分钟,获取资源的时候直接判断。 和账号系统独立开,可以把资源放在第三方的系统。 浏览器ajaxcookie可以设置可以设置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))
    }
})

微信公众号:前端linong


原文:SegmentFault

评论

评论功能即将开放。你也可以通过 邮件GitHub Issue 反馈。