axios 文件下载和存储导致文件损坏(编码问题)?

axios file download and storing leads in a corrupt file (encoding problem)?

我有一个典型的 JPG 文件,我使用 axios 下载并存储在磁盘上,如下所示:

// Just create axios instance that does not care about HTTPS certificate validity
// since I need to download from an untrusted internal service. 
// Included for completeness. Do not borrow this bit unless you know what you are doing. 
const axiosInstance = axios.create({
    httpsAgent: new https.Agent({
        rejectUnauthorized: false
    })
});
// Download file
fileData = await axiosInstance.get(imageUrl, {
    responseType: 'arraybuffer',

});
console.log(`Dowloaded OK, size ${fileData.data.length} bytes`));
// Dump file to disk
await fs.writeFile(`${filename}`, fileData.data, (err) => {}
});

我观察到虽然 console.log 报告了正确的字节数并且 fileData.data 在调试器中看起来不错,但记录的文件有两倍的字节数并且自然损坏了。似乎非英文字母变成了 2 个字节而不是一个。我怀疑它与编码有关。

我如何才能更正此问题以便正确记录文件?

我猜是你怎么调用的问题writeFile,我建议你尝试一下

fs.writeFile(`${filename}`, { encoding: 'binary' }, fileData.data, (err) => {})
// or
fs.writeFile(`${filename}`, Buffer.from(fileData.data), (err) => {})

但是,正确的方法是在数据传入时使用流,并直接写入磁盘。

这样程序会使用更少的内存,而且会很省时。程序不会等待所有数据下载并保存在 RAM 中,然后尝试写入磁盘,而是“即时”写入磁盘。

工作示例:

const axios = require('axios')
const path = require('path')
const fs = require('fs')

const target_path = path.resolve(__dirname, 'some_random_filename')
const input = fs.createWriteStream(target_path, 'binary')

axios
  .get('https://via.placeholder.com/150', {
    responseType: 'stream'
  })
  .then(res => res.data.pipe(input))
  .catch(err => console.error(err))

参考文献: