ama
ama copied to clipboard
重複使用 createReadStream
感謝使用 Node.js Taiwan AMA,以下附上簡單提問範例供參考,請把內容改成你自己遇到的問題
目的
我希望使用Nodejs 呼叫 API 上傳圖片到server
使用的工具
希望使用 form 的方式上傳檔案 ( https://www.npmjs.com/package/form-data ) 我使用的是範例程式裡面的第三種方法
使用 fs.createReadStream的方法讀取圖片 最後post 這個 form 物件到 API去
form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
操作流程
我會多次呼叫上傳 API 因為不希望每次都要重新讀取一次圖片 (fs.createReadStream) 所以在迴圈外面先讀取一次檔案, 像下面這樣:
const fileStream= fs.createReadStream('/foo/bar.jpg'));
(async()=>{
for(let i=0;i<3;i++){
const formData=new FormData();
formData.append('file', fileStream);
await axios.post('url', {data:formData} ) // 呼叫API 上傳剛剛的檔案
}
})();
遇到的問題
API都會回應 http 504 timeout
嘗試過的解法
-
將createReadStream放在迴圈裡面, 即每次呼叫都重新讀取檔案 可正常執行 (但是拉出來回圈外面就會失敗) 查了原因應該是因為readStream 被讀取一次後 該stream 狀態就變成 readable: false
-
嘗試改存成 buffer (像form-data的第二種方法 如下:)
form.append('my_buffer', new Buffer(10));
配合使用fs.readfile的方法
但是使用form-data 送到 API 時 就會失敗 好像只能用createReadStream能成功
用 buffer 是可以正常執行的
const fs = require('fs');
const axios = require('axios');
const FormData = require('form-data');
try {
(async () => {
const buffer = await fs.promises.readFile(__dirname + '/ttt.png');
const formData = new FormData();
formData.append('avatar', buffer, {filename: 'ttt.png'});
formData.append('name', 'shinder');
for (let i = 0; i < 3; i++) {
await axios.post(
'http://localhost:3000/form1',
formData.getBuffer(),
{
headers: formData.getHeaders()
});
}
})()
} catch(ex) {
console.log('ex:', ex);
}