axios 文件下载并将线索存储在损坏的文件中(编码问题)?

Ask*_*mov 2 fs node.js axios

我有一个典型的 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) => {}
});
Run Code Online (Sandbox Code Playgroud)

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

我怎样才能纠正这个问题以便正确记录文件?

Ana*_*azy 6

我猜问题出在你打电话的方式上writeFile,我建议你尝试一下

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

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

这样程序将使用更少的内存,并且时间效率更高。程序不会等待所有数据下载并保存在 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))
Run Code Online (Sandbox Code Playgroud)

参考: