Bootstrap

<a>链接下载视频/图, 不是打开新页面预览

转自:<a>链接下载视频 而不是打开新页面播放_小垚尧的博客-CSDN博客_a标签下载视频文件

开发中我们常用<a标签>链接下载数据, 非常好用。但是在下载视频的时候 会遇到无法下载 转而打开新页面播放的bug
其实, 查看该响应的headers你就会发现, 它的 Response Headers 中有一条: Content-Type: text/html; charset=UTF-8
没错,当我们点击那个a标签时,浏览器检查了response的Content-Type,发现如果是text/html, 浏览器就会打开页面。当然, 如果这是一个特殊的类型(比如: application/octet-stream),就会触发下载行为。

Content-Type头部的内容实际上是MIME类型,用来表示文档、文件或字节流的性质和格式。浏览器就是根据这个MIME来识别不同的response,并决定如何处理它。

当然, 不光response会有, 其实, 我们发送request的时候, 对于特殊格式的数据, 也会设置特殊的Content-Type, 最常见的就是文件file的提交, 通常会设置'Content-Type': 'multipart/form-data',

现在问题来了,如果要下载的文件本身是一个html,怎么办呢?

将Content-Type手动修改为application/octet-stream可以吗?当然可以,这样浏览器就会认为a标签引用的是一个二进制文件,直接触发下载行为。但是这样做显得太暴力了,下载文件的类型信息丢失了,有没有其他办法呢?

那就是Content-Disposition这个header。Content-Disposition可以告诉浏览器,获取到的资源是展示还是下载,比如:

Content-Disposition: attachment; filename=hello.html

这样,我们就可以让Content-Type是text/html,同时浏览器也能正确识别并下载html文件了。

下面贴上具体的封装方法:

/**
 * 根据链接下载视频
 * @param {string} filePath 文件地址
 * @param {string} fileName 文件名
 */
export function videoDownload(filePath: string, fileName: string) {
    const a = document.createElement('a');
    document.body.append(a);
    a.style.display = 'none';
    
    // 指示回复的内容该以何种形式展示(是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。)
    a.href = filePath + '&response-content-disposition=' + encodeURIComponent('attachment; filename="' + fileName + '"');
    a.download = fileName;
    a.click();
    
    // 多文件时remove放在setTimeout里面
    setTimeout(() => {
        document.body.removeChild(a);
    }, 300);
}

;