【问题标题】:Unable to convert response data of octet-stream to Zip file and download it无法将八位字节流的响应数据转换为 Zip 文件并下载
【发布时间】:2020-07-31 10:50:08
【问题描述】:

我正在尝试从 AJAX GET 请求下载包含 JSON 文件的 Zip 文件。

响应头格式:

Connection: keep-alive
content-disposition: attachment;filename=exportedFiles_ 1.6.0_20200731160652.zip
Content-Length: 4496
Content-Type: application/octet-stream
Date: Fri, 31 Jul 2020 10:36:52 GMT

网络选项卡中的数据预览:

AJAX调用及成功函数:

$.ajax({
      type: "GET",
      url: "/download/" ,
      async: false,
      success: function (data,status, xhr) {          
      var filename = xhr.getResponseHeader('content-disposition').split("filename=")[1];;
      var blob = new Blob([data], {type: "octet/stream"})
       saveAs(blob, filename); 
      }
    });

它正在保存 Zip 文件,但是当我尝试打开 Zip 文件时,它显示“Windows 无法打开文件夹,压缩的 Zip 无效”。

【问题讨论】:

  • 遇到类似问题,请问您解决了吗?

标签: javascript ajax rest download zip


【解决方案1】:

为 Received 文档实现一个Axios 处理程序,数据格式为octect-stream, data 可能看起来很奇怪 PK something JbxfFGvddvbdfbVVH34365436fdkln 作为它的八位字节流格式,您最终可能会使用此数据创建文件可能已损坏,{responseType: 'blob'} 会将数据转换为可读格式,

axios.get("URL", {responseType: 'blob'})
     .then((r) => {
         let fileName =  r.headers['content-disposition'].split('filename=')[1];
         let blob = new Blob([r.data]);
         window.saveAs(blob, fileName);             
      }).catch(err => {
        console.log(err);
      });

您可能已经尝试过像这样失败的解决方案, window.saveAs(blob, 'file.zip') 将尝试将文件另存为 zip 但不会工作,

const downloadFile = (fileData) => {
    axios.get(baseUrl+"/file/download/"+fileData.id)
        .then((response) => {
            console.log(response.data);
            const blob = new Blob([response.data], {type: response.headers['content-type'], encoding:'UTF-8'});
            const link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download = 'file.zip';
            link.click();
        })
        .catch((err) => console.log(err))
}
const downloadFile = (fileData) => {
axios.get(baseUrl+"/file/download/"+fileData.id)
    .then((response) => {
        console.log(response);
        //const binaryString = window.atob(response.data)
        //const bytes = new Uint8Array(response.data)
        //const arrBuff = bytes.map((byte, i) => response.data.charCodeAt(i));
        //var base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(response.data)));
        const blob = new Blob([response.data], {type:"application/octet-stream"});
        window.saveAs(blob, 'file.zip')
        // const link = document.createElement('a');
        // link.href = window.URL.createObjectURL(blob);
        // link.download = 'file.zip';
        // link.click();
    })
    .catch((err) => console.log(err))
}
function base64ToArrayBuffer(base64) {
    var binaryString = window.atob(base64);
    var binaryLen = binaryString.length;
    var bytes = new Uint8Array(binaryLen);
    for (var i = 0; i < binaryLen; i++) {
        var ascii = binaryString.charCodeAt(i);
        bytes[i] = ascii;
    };

    return bytes;
}

另一个简短的解决方案是,

window.open("URL")

将继续不必要地打开新标签,用户可能必须使用 allow popups 才能使用此代码,如果用户想同时下载多个文件,那么请先使用解决方案,或者如果不尝试其他解决方案,该怎么办

【讨论】:

    【解决方案2】:

    将响应类型设置为arraybuffer:

    dataType: 'arraybuffer'
    

    【讨论】:

    • 什么数据类型和在哪里写这个以及这将如何解决这个问题?
    • 在 ajax 请求中:$.ajax({ type: "GET", url: "/download/" , async: false, success: function (data,status, xhr) { var filename = xhr.getResponseHeader('content-disposition').split("filename=")[1];; var blob = new Blob([data], {type: "octet/stream"}) saveAs(blob, filename); }, dataType: 'arraybuffer' }); dataType 参数用于“期望”从服务器返回的自定义类型。
    猜你喜欢
    • 1970-01-01
    • 2016-09-27
    • 2020-04-09
    • 1970-01-01
    • 2020-07-09
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 2020-11-05
    相关资源
    最近更新 更多