下载二进制文件自动添加后缀

352 阅读2分钟

需求描述

批量接管实例功能需要增加一个离线检查工具下载功能,该工具为一个二进制文件。点击下载可下载该二进制文件到本地。

问题描述

本身项目里已经封装了一个工具函数用于文件下载:

  public downloadByCreateElementA(fileStream: any, fileName?: string) {
    const url = window.URL.createObjectURL(new Blob([fileStream]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', fileName ? fileName : 'file');
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }
  //组件中调用
const downloadOfflineCheckTool = () => {
    MysqlService.DownloadMysqlTakeoverInspectTool({
     responseType: 'blob'
    })
      .then((res) => {
        Download.downloadByCreateElementA(res, 'mysql_takeover_inspect_tool');
      })
      .catch((err) => {
        showRequestError(err.data);
      });
};

自测发现,此时可以下载到文件,但下载到本地的文件均以.txt结尾。

解决方法

downloadByCreateElementA新增可选参数config,指定typeapplication/octet-stream

  const downloadOfflineCheckTool = () => {
    MysqlService.DownloadMysqlTakeoverInspectTool({
      responseType: 'blob',
    })
      .then((res) => {
        Download.downloadByCreateElementA(res, 'mysql_takeover_inspect_tool', {
          type: 'application/octet-stream',
        });
      })
  };
  public downloadByCreateElementA(
    fileStream: any,
    fileName?: string,
    config?: { type: string }
  ) {
    let blob: Blob;
    if (!!config) {
      blob = new Blob([fileStream], config);
    } else {
      blob = new Blob([fileStream]);
    }
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', fileName ? fileName : 'file');
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }

原因

相对原本的代码,修改后的代码只是在创建Blob对象时,指定了type参数为application/octet-stream,而不是默认的空字符串。如果在设置download的时候没有强制指定文件后缀名,浏览器可能会根据文件内容尝试猜测文件类型并添加默认的扩展名

MIME type

在了解Blob对象之前需要先理解什么是MIME type。MIME typemeida Type的子集,由媒体类型和子类型组成,中间由斜杠分隔。比如text/html。MIME type是用来告诉web浏览器如何处理媒体内容,常见类型如下:

type处理方式
text/plain普通文本
text/html普通网页
text/css级联样式表
text/javascript脚本
application/octet-stream下载文件
application/x-java-appletJava applets
application/pdfpdf文档

对于空字符串的处理方式取决于具体的应用、框架或者服务器,比如:

  1. 服务器将其解释为默认的mime type
  2. 将其看做错误,返回带有错误码的响应
  3. 根据文件扩展名或者对内容结构进行解析,自动检测mime type
  4. 直接忽略

Blob对象

Blob对象代表一个类文件对象,具有以下特征:

  • 一旦创建就不可修改。
  • 包括文本和二进制数据等任意类型的数据,可以用来处理纯文本、json、图像、视频等类型的原始数据
  • 可以转换为ReadableStream用于数据操作

Blob构造函数

语法:

new Blob(blobParts,{
    type?:(mimeType),
    endings?:(transparent|native)//不推荐
}) //返回新的Blob对象

blobParts参数不仅仅指数组,而是指所有的可迭代对象(ArrayBuffer,TypedArray,DataView,Blob,string,或者混合体)。而type参数指的是将会被存储到blob中的数据的MIME类型。

总结:

如果没有在download中指定下载文件的后缀,就必须在创建Blob对象的时候指定type