我使用 multiparty 解析前端上传的文件,然后使用 request 上传到文件服务器。
form.on('part', function(part) {
if (part.filename) {
var formData = {
name: part.filename,
my_file: part
};
request.post({
url: 'http://service.com/upload',
formData: formData
}, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});
}
});
request的官方示例是将文件的 readStream , 传入 formdata。例如
var formData = {
my_file: fs.createReadStream(__dirname + '/unicycle.jpg'),
}
但是我并不想先创建临时文件,然后再获取 readStream。 由于 multiparty的 part 也是一种可读流, transform stream,它同时具有 readStream 和 writeStream 的接口,所以我想将 part 直接传入formdata。 但是遇到了下面的错误
TypeError: form-data: Invalid non-string/buffer chunk
由于文件服务器是远端的线上服务器,它的细节我并不清楚。 但是它确实能支持从文件创建的 readStream 的 formdata 的上传。 但是 part 就不行。
这里想请教一下, transform stream 和 fs.createStream 有什么不同? 有什么办法可以将 transform stream 的数据 转交给 readStream? 谢谢。
好吧, 我自己找到答案了。
使用 form-data
使用 form-data
問題中提到的 part 是一種 transform 流, 這種流一般用於對資料進行transform,也就是轉換。它既可讀,亦可寫,實際上是當有資料輸入時,才會輸出。可以把它想像成一個轉換數據的盒子。
requset 模組可以post form data,像這樣。
這個form只是單純的 js 對象,request 會將它轉換為 formdata。
request 可以從 streamObj 中獲取到它需要的所有信息,但是這個 stream 只支援 fs.readStream, http.response 。 對於其他 stream,需要提供與文件相關的資訊。
下面是原文,大概意思是上面說的。
所以,必須用下面的方式建構 form,原始的 form-data,當然,首先你得 npm install form-data。
filename,headers,byteCount 都是 part 的自有屬性。
設定 http header Transfer-Encoding: chunked
當part事件觸發時,說明客戶端表單中的文件部分開始上傳到當前伺服器了,這個時候,我們將part 交給發送資料到 檔案伺服器的http request。此時,必須給這個 request 指定一個header
這是為什麼呢? 因為,content-length 此時是不確定的,因為客戶端的資料還沒上傳完畢。我們必須告知文件伺服器,請求的長度還不確定,你必須等我說停才能停。
這就是設定這個 header 的意義。
用pipe試試?