我試着拉上一堆文件並將其上傳到遠程服務器(這也是寫的NodeJS和使用表單處理多方)上傳文件,而無需使用請求模塊臨時文件的NodeJS
,但我想要的要做到這一點就是不用臨時文件。這意味着「:創建一個zip壓縮包的流,並直接通過request
模塊上傳流」
,所以我寫了一些測試代碼,首先是接收上傳服務器:
var multiparty = require('multiparty');
var http = require('http');
var util = require('util');
http.createServer(function(req, res) {
if (req.url === '/upload' && req.method === 'POST') {
// parse a file upload
var form = new multiparty.Form({encoding: null});
console.log("what?");
form.parse(req, function(err, fields, files) {
if (err) {
console.error(err);
}
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
return;
}
// show a file upload form
res.writeHead(200, {'content-type': 'text/html'});
res.end(
'<form action="/upload" enctype="multipart/form-data" method="post">'+
'<input type="text" name="title"><br>'+
'<input type="file" name="upload" multiple="multiple"><br>'+
'<input type="submit" value="Upload">'+
'</form>'
);
}).listen(8080);
然後我只是用child_process執行zip
命令,但不是創建一個臨時文件,我輸出存檔,以便標準輸出來創建流:
/*
upload a manually-created readable stream from string output from zip command.
*/
var exec = require('child_process').exec;
var dir = '/Users/drakedan/Documents/screenshot/1457950544039/';
var zipCmd = 'zip -r9 - ' + dir;
var Stream = require('stream');
var request = require('request');
var fs = require('fs');
exec(zipCmd, {encoding: null}, function(err, stdout, stderr) {
if (err) console.error(err);
var rs = Stream.Readable({encoding: null});
rs.push(stdout);
rs.push(null);
var req = request.post('http://127.0.0.1:8080/upload', function(err, httpResponse, body) {
if (err) console.error(err);
console.log(body);
});
var form = req.form();
form.append('image', rs);
})
但我跑得後上傳腳本,服務器返回
{ [Error: stream ended unexpectedly] status: 400, statusCode: 400 }
只是好像有什麼不對的可讀流。
爲了檢查該流內容是否有損壞。我將腳本修改爲使用臨時文件。
/*
first write the stream content to a temp file, then
upload a new stream from the temp file.
*/
var exec = require('child_process').exec;
var dir = '/Users/drakedan/Documents/screenshot/1457950544039/';
var zipCmd = 'zip -r9 - ' + dir;
var Stream = require('stream');
var request = require('request');
var fs = require('fs');
exec(zipCmd, {encoding: null}, function(err, stdout, stderr) {
if (err) console.error(err);
var rs = Stream.Readable({encoding: null});
rs.push(stdout);
rs.push(null);
var ws = fs.createWriteStream('/Users/drakedan/Desktop/test.zip');
rs.pipe(ws);// create a temp file.
rs.on('end', function(){
var req = request.post('http://127.0.0.1:8080/upload', function(err, httpResponse, body) {
if (err) console.error(err);
console.log(body);
});
var form = req.form();
form.append('image', fs.createReadStream('/Users/drakedan/Desktop/test.zip')); // readstream from temp file
});
});
這次,服務器接受該文件。
received upload:
{ fields: {}, files: { image: [ [Object] ] } }
並且臨時文件可以被成功解壓縮,這意味着沒有內容損壞。
所以我的問題是:
什麼是處理這種情況的正確方法?
fs.createReadStream
和我手動創建的可讀流之間有什麼區別。
我有什麼機會可以流過整個過程?
我做錯了什麼?