前端下载二进制流文件

一、两种方式:

  1、后台提供一个 URL,然后用 window.open(URL) 下载

  2、后台直接返回文件的二进制内容,然后前端转化一下再下载

二、Blob对象:

  1、Blob,全称:Binary Large Object,表示不可变的类似文件对象的二进制数据。

  2、构造函数:Blob(blobParts[, options])

   参数说明:

  • blobParts:数组类型, 数组中的每一项连接起来构成Blob对象的数据,数组中的每项元素可以是ArrayBuffer(二进制数据缓冲区), ArrayBufferView,Blob,DOMString。或其他类似对象的混合体。
  • options:可选项,字典格式类型,可以指定如下两个属性:
    • type,默认值为"",它代表了将会被放入到blob中的数组内容的MIME类型。
    • endings, 默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。它是以下两个值中的一个: "native",表示行结束符会被更改为适合宿主操作系统文件系统的换行符; "transparent",表示会保持blob中保存的结束符不变。

    常用写法:var blob = new Blob([res], { type: res.type });

      解释:res 为请求响应结果,使用 type 指定MIME类型(否则为"")

  3、使用场景:

  • 分片上传
  • Blob URL:Blob URL是blob协议得URL,它的格式如 blob:http://xxx。它可以通过window.URL.createObjectURL(blob)创建。在绝大部分场景下,我们可以像使用Http协议得URL一样使用Blob URL。常见得场景有作为文件得下载地址和作为图片资源地址。

三、根据前端返回的二进制文件流下载文件:

  示例代码:当文件状态改变时触发上传批量导入文件,批量导入完成后会返回一个反馈文件的二进制流,我们需要将该二进制流下载为文件。

    fileChange(file) {

      const formData = new FormData();

      this.$confirm('是否上传此文件?', '提示', {

          confirmButtonText: '确定',

          cancelButtonText: '取消',

          type: 'warning'

        }).then(() => {

          formData.append('file', file.raw)

          iccard.batchImport(formData).then((res) => {

                const blob = new Blob([res], { type: res.type });

            let dom = document.createElement("a");

            let url = window.URL.createObjectURL(blob);

            dom.href = url;

            dom.download = decodeURI('批量导入结果反馈.xlsx');

            dom.style.display = "none";

            document.body.appendChild(dom);

            dom.click();

            dom.parentNode.removeChild(dom);

            window.URL.revokeObjectURL(url);

           });

           this.$message({

             type: 'success',

             message: '上传成功!'

           });

        }).catch(() => {

          this.$message({

            type: 'info',

            message: '取消上传'

          });         

        });

    },

  总结:大体思路就是获取到文件url,然后通过创建document节点--超链接,为节点绑定一个点击事件。

四、之后加的需求:

    因为之前没有考虑到excel格式、服务器异常等情况,所以当出现500错误时还是会在导入完成后下载文件,但是下载出的文件报了500且存在乱码,此时我们的需求就是出现500时不下载文件,只在前端提示用户。

  解决:

    因为相应的api接口中要求数据返回类型为 ”blob“,所以非文件处理的请求拦截器不适用,那么我们就新创建一个拦截器文件,专门处理文件下载请求。

    其次,在方法中通过对 type 的判断来决定是否要下载导入后的反馈文件还是进行错误提示。

    其中,加深了我对响应字段 content-type 的理解,后端一般返回的数据类型都是 application/json ,excel文件的话就是 application/vnd.ms-excel ,所以我们可以根据这点来进行相应的判断。

    最后,对 api 接口中的 responseType: "blob"  还是有点不理解,它到底起了什么作用?

    代码:

		  iccard.batchImport(formData).then((res) => {
            if (res.data.type == "application/json") {
              var innerData;
              var reader = new FileReader();
              reader.readAsText(res.data, "utf-8");
              reader.onload = () => {
                     innerData = JSON.parse(reader.result);
                if (innerData.code == 500) {
                  this.$notify({
                    type: "error",
                    message: innerData.msg,
                  });
                  return;
                }
                  };
            }else if (res.data.type == "application/vnd.ms-excel") {
              fileUtil
                .downloadFile(res, "批量导入结果反馈")
                .then(() => {
                  this.$notify({
                    type: "success",
                    message: "下载成功",
                  });
                })
                .catch(() => {
                  this.$notify({
                    type: "error",
                    message: "下载失败",
                  });
                });
            } else {
              this.$notify({
                type: "error",
                message: "文件格式不正确",
              });
            }
          });

<think>好的,用户想知道如何在前端实现二进制流文件下载。我需要根据提供的引用内容来整理步骤,并给出示例。首先,引用[1]提到前端可以决定下载文件名,这需要注意。引用[2]指出需要设置XMLHttpRequest的responseType为'blob',否则文件会损坏。引用[3]则建议使用axios,并设置请求体。 首先,步骤应该包括设置正确的响应类型,将数据转换为Blob对象,创建URL,以及触发下载。还要注意设置Content-Disposition头部来获取文件名,不过如果后端没提供,前端可以自己命名。 可能需要分步骤说明:使用原生XMLHttpRequest和axios两种方法。同时,要处理文件名的问题,比如通过正则从响应头提取,或者前端指定。代码示例需要正确,比如使用URL.createObjectURL和a标签的下载属性。 还要考虑可能的错误,比如忘记设置responseType导致文件损坏,这时候要提醒用户检查这个设置。另外,跨域问题可能影响下载,但用户没提到,可能不需要深入。最后,生成相关问题,比如优化方法或不同格式的处理。</think>### 前端实现二进制流文件下载的方法 #### **核心步骤** 1. **设置响应类型**:确保请求的`responseType`设置为`blob`,以正确处理二进制流数据[^2]。 2. **转换数据为Blob对象**:将接收的二进制流封装为`Blob`对象。 3. **生成临时URL**:通过`URL.createObjectURL`生成可下载的链接。 4. **触发下载**:创建隐藏的`<a>`标签,模拟点击实现下载5. **文件名处理**:优先从响应头`Content-Disposition`提取文件名,若后端未提供,前端可自定义[^1]。 --- #### **示例代码** ##### 方法1:原生XMLHttpRequest ```javascript function downloadFile(url, filename) { const xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = 'blob'; // 关键:声明响应类型为blob xhr.onload = function() { if (xhr.status === 200) { const blob = new Blob([xhr.response]); const downloadUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = downloadUrl; a.download = filename || extractFilename(xhr); // 从响应头提取或自定义 document.body.appendChild(a); a.click(); URL.revokeObjectURL(downloadUrl); document.body.removeChild(a); } }; xhr.send(); } // 从响应头提取文件名(需后端支持) function extractFilename(xhr) { const disposition = xhr.getResponseHeader('Content-Disposition'); return disposition ? disposition.match(/filename="?(.+?)"?(;|$)/)[1] : 'file'; } ``` ##### 方法2:Axios实现 ```javascript axios({ method: 'get', url: '/api/download', responseType: 'blob' // 关键:声明响应类型为blob[^3] }).then(response => { const blob = new Blob([response.data]); const downloadUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = downloadUrl; a.download = 'custom_filename.pdf'; // 前端自定义文件名[^1] document.body.appendChild(a); a.click(); URL.revokeObjectURL(downloadUrl); document.body.removeChild(a); }); ``` --- #### **注意事项** 1. **跨域问题**:若接口跨域,需后端配置`Access-Control-Expose-Headers`以暴露`Content-Disposition`头。 2. **文件类型**:通过`Blob`的第二个参数指定MIME类型,例如`new Blob([data], { type: 'application/pdf' })`。 3. **大文件处理**:使用分块下载或流式处理避免内存溢出。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值