我有一个典型的 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 个字节。我怀疑这与编码有关。
我怎样才能纠正这个问题以便正确记录文件?
我猜问题出在你打电话的方式上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)
参考: