axios如何处理responseType为blob和arraybuffer的情况?

7 浏览
0 Comments

axios如何处理responseType为blob和arraybuffer的情况?

我正在使用axios下载一个zip文件。为了进一步处理,我需要获取已下载的“原始”数据。据我所知,在JavaScript中有两种类型可以实现这一点:Blobs和Arraybuffers。这两种类型都可以在请求选项中指定responseType

接下来,需要解压缩zip文件。我尝试了两个库:js-zip和adm-zip。这两个库都需要数据是ArrayBuffer类型。到目前为止,我可以将Blob转换为Buffer。在此转换之后,adm-zip总是可以成功提取zip文件。然而,js-zip会抱怨文件损坏,除非zip文件是以'arraybuffer'作为axios的responseType下载的。js-zip无法处理从Blob中获取的Buffer。

这让我感到非常困惑。我本以为ArrayBuffer和Blob本质上只是底层内存的视图。在以Blob或Buffer的方式下载文件之间可能存在性能差异。但结果数据应该是相同的,对吗?

好吧,我决定进行实验,并发现了以下结果:

如果你指定responseType: 'blob',axios会将response.data转换为字符串。假设你对该字符串进行哈希处理并得到哈希码A。然后你将其转换为Buffer。在此转换中,你需要指定一种编码。根据编码的不同,你将得到各种新的哈希码,我们称之为B1、B2、B3,等等。当以'utf8'作为编码时,我可以得到原始哈希码A。

所以我猜当以'blob'方式下载数据时,axios会隐式地将其转换为用utf8编码的字符串。这似乎非常合理。

现在你指定responseType: 'arraybuffer'。Axios将以response.data的形式提供一个Buffer。对该Buffer进行哈希处理,你将得到哈希码C。这个码不对应于A、B1、B2等等的任何码。

所以当以'arraybuffer'方式下载数据时,你得到的是完全不同的数据?

现在我明白了,如果数据以'blob'方式下载,解压缩库js-zip会抱怨数据已损坏。它可能确实已经损坏了。但是adm-zip如何能够提取它?我检查了提取出来的数据,它是正确的。这可能仅适用于特定的zip归档文件,但仍然让我感到惊讶。

以下是我用于实验的示例代码:

//typescript import syntax, this is executed in nodejs
import axios from 'axios';
import * as crypto from 'crypto';
axios.get(
    "http://localhost:5000/folder.zip", //hosted with serve
    { responseType: 'blob' }) // replace this with 'arraybuffer' and response.data will be a buffer
    .then((response) => {
        console.log(typeof (response.data));
        // first hash the response itself
        console.log(crypto.createHash('md5').update(response.data).digest('hex'));
        // then convert to a buffer and hash again
        // replace 'binary' with any valid encoding name
        let buffer = Buffer.from(response.data, 'binary');
        console.log(crypto.createHash('md5').update(buffer).digest('hex'));
        //...

是什么导致了这种差异,我该如何获取“真实”的已下载数据?

0