我相信,如果你想要做的POST,您必須使用Content-Type: multipart/form-data;boundary=myboundary
標題。然後,在身體,write()
這樣的事情每串場(換行符應該是\r\n
):
--myboundary
Content-Disposition: form-data; name="field_name"
field_value
,然後對文件本身,write()
像這樣對身體:
--myboundary
Content-Disposition: form-data; name="file"; filename="urlencoded_filename.jpg"
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
binary_file_data
的binary_file_data
是在您使用pipe()
:
var fileStream = fs.createReadStream("path/to/my/file.jpg");
fileStream.pipe(requestToGoogle, {end: false});
fileStream.on('end, function() {
req.end("--myboundary--\r\n\r\n");
});
的{end: false}
防止pipe()
不會自動關閉請求,因爲在完成發送文件後您需要再寫一個邊界。請注意邊界末端的額外--
。
大疑難雜症是,谷歌可能需要content-length
頭(很可能)。如果是這種情況,那麼您無法將用戶的POST流式傳輸到Google發佈的POST,因爲在您收到整個文件之前,您無法可靠地知道content-length
是什麼。
的content-length
標頭的值應該是整個身體的單個數字。要做到這一點的簡單方法是在整個機構上撥打Buffer.byteLength(body)
,但如果您有大型文件,它會很快變得醜陋,並且也會導致流式傳輸。另一種方法是,計算它像這樣:
var body_before_file = "..."; // string fields + boundary and metadata for the file
var body_after_file = "--myboundary--\r\n\r\n";
var fs = require('fs');
fs.stat(local_path_to_file, function(err, file_info) {
var content_length = Buffer.byteLength(body_before_file) +
file_info.size +
Buffer.byteLength(body_after_file);
// create request to google, write content-length and other headers
// write() the body_before_file part,
// and then pipe the file and end the request like we did above
但是,仍然殺死你從用戶到流式傳輸到谷歌的能力,該文件已被下載到本地磁盤,以確定它的長度。
備用選項
...現在,經過了這一切後去,PUT可能會在這裏你的朋友。根據https://developers.google.com/storage/docs/reference-methods#putobject,您可以使用transfer-encoding: chunked
標題,因此不需要查找文件長度。而且,我相信請求的全部內容僅僅是文件,因此您可以使用pipe()
,並在請求完成時讓它結束請求。如果您使用https://github.com/felixge/node-formidable來處理上傳,那麼你可以做這樣的事情:
incomingForm.onPart = function(part) {
if (part.filename) {
var req = ... // create a PUT request to google and set the headers
part.pipe(req);
} else {
// let formidable handle all non-file parts
incomingForm.handlePart(part);
}
}
不幸的是,谷歌需要它是爲了做什麼,我試圖做一個POST請求。然而,偉大的答案,我一定會實施你提出的建議。 – jwegner 2012-04-02 13:10:52
另外,順便說一下,node.js讓你能夠[關閉連接管道](http://nodejs.org/api/stream.html#stream_stream_pipe_destination_options) – jwegner 2012-04-02 20:31:40
好點,我忘記了這一點。我會編輯答案,以防其他人遇到它。 – 2012-04-02 21:42:06