后端返回blob文件流,前端下载文件的整个过程,偏向于前端这边(vue+axios)

先谈谈遇到的问题吧:

1. 后端接口返回的blob文件流,你下载下来的文件是乱码的?

解决办法 :让你的后端设置流的编码为utf-8。请跟后端大佬说,一定要给blob格式的文件流。

2. 后端返回的blob文件流,并且已经设置了utf-8,但是你接受的接口返回值,依然是乱码?

解决办法: 肯定没有设置 responseType: "blob",我不知道你用的什么接口请求方式,你可以搜一下,怎么设置responseType: "blob"

3. 下载word文件里面内容是【object object】或者下载的图片是损坏的?

解决办法:参考以上的1和2答案,确定1和2都没有问题。

那么还有个原因就是:response 中还有一层data ,如果直接用blob流,文件里面就是object。你就把文件流的response.data一下

 

下面附上 后端返回blob的文件流,前端下载、打印、预览文件的方法

本人用的vue,不管你用的什么技术库,原理一样,都是js。废话少说,直接上代码:

下载功能实现:

    // 调用下载接口,返回bolb文件流
      axios({
        method: "get",
        url: this.proxyUrl + "/api/file/downloadFile", //后端下载接口地址
        responseType: "blob",  // 设置接受的流格式
        params: { // get方式,请写params, post方式写data,这里是get方式的传参
          fileId: this.selectedTabelRow[0].fileId,
          type: val,
        },
      }).then((res) => {
        // res 中还有一层data ,如果直接用blob流,文件里面是object,我就是犯错了。
        this.handleExport(res.data);
      });

   /* 下载文件的公共方法,参数就传blob文件流*/
    handleExport(data) {
      // 动态创建iframe下载文件
      let fileName = this.selectedTabelRow[0].dirName;
      if (!data) {
        return;
      }
      let blob = new Blob([data], { type: "application/octet-stream" });
      if ("download" in document.createElement("a")) {
        // 不是IE浏览器
        let url = window.URL.createObjectURL(blob);
        let link = document.createElement("a");
        link.style.display = "none";
        link.href = url;
        link.setAttribute("download", fileName);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link); // 下载完成移除元素
        window.URL.revokeObjectURL(url); // 释放掉blob对象
      } else {
        // IE 10+
        window.navigator.msSaveBlob(blob, fileName);
      }
    },

以上就是下载的方法啦,不好用,你砍我!!!!!

别别别 你私我,我随时在线。

打印功能实现: 

也是直接上代码:

// 调用打印接口,我们这边是后端弟兄,把所有的word格式全部给转化成了pdf格式,还添加了水印
    axios({
        method: "post",
        url: this.proxyUrl + "/api/file/printdocument",
        responseType: "blob",
        headers: { "Content-Type": "application/json" },
        data: { // post格式是data传参数,注意请求方式
          file_id: this.selectedTabelRow[0].fileId,
          addwatermark: val,
        },
      }).then((res) => {
        res = res.data;
        const blob = new Blob([res], { type: "application/pdf" }); // 因为知道是pdf所以指定了格式。
        var date = new Date().getTime();
        var ifr = document.createElement("iframe");
        ifr.style.frameborder = "no";
        ifr.style.display = "none";
        ifr.style.pageBreakBefore = "always";
        ifr.setAttribute("id", "printPdf" + date);
        ifr.setAttribute("name", "printPdf" + date);
        ifr.src = window.URL.createObjectURL(blob);
        document.body.appendChild(ifr);
        this.doPrint("printPdf" + date);
        window.URL.revokeObjectURL(ifr.src); // 释放URL 对象
      });
// 打印
    doPrint(val) {
      var ordonnance = document.getElementById(val).contentWindow;
      setTimeout(() => {
        // window.print()
        ordonnance.print();
        this.pdfLoading = false;
      }, 100);
    },

预览功能实现: 

预览功能我用的是vue-pdf这个npm包。同样预览也是java的弟兄给转成了pdf,我直接预览pdf格式就行,不过,返回的是文件流,不是url地址。所以需要先把流转化成url地址,很简单一个方法搞定。

// 将返回的流数据转换为url
    getObjectURL(file) {
      let url = null;
      if (window.createObjectURL != undefined) {
        // basic
        url = window.createObjectURL(file);
      } else if (window.webkitURL != undefined) {
        // webkit or chrome
        try {
          url = window.webkitURL.createObjectURL(file);
        } catch (error) {}
      } else if (window.URL != undefined) {
        // mozilla(firefox)
        try {
          url = window.URL.createObjectURL(file);
        } catch (error) {}
      }
      return url;
    },

其他的使用方法就是跟vue-pdf教程一样了。

踩坑记录一下!!!之前也做过根据url来下载文件,算是比较简单的,这次的文件流,倒是踩出来了很多坑。

你可能感兴趣的:(vue,js笔记)