node.js 将上传的文件通过管道传输到具有节点的远程服务器(理想情况下具有相同的文件名)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32138748/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Pipe a uploaded file to a remote server with node (ideally with same filename)
提问by svenhornberg
I want to upload a file in my app.js server , which should pipe that file to a crossdomain server like my upload.js server.
我想在我的 app.js 服务器中上传一个文件,该文件应该将该文件传输到像我的 upload.js 服务器这样的跨域服务器。
The full code can be found under the following link
完整代码可以在以下链接中找到
The upload.js server is working. My problem is the app.js server. Request seems to be capable of streaming files (https://github.com/request/request#streaming). But I dont get it working. I am always getting : [Error: Invalid protocol] in my app.js.
upload.js 服务器正在工作。我的问题是 app.js 服务器。请求似乎能够流式传输文件(https://github.com/request/request#streaming)。但我不明白它的工作。我总是在我的 app.js 中得到:[错误:无效的协议]。
It musst be this line:
必须是这一行:
fs.createReadStream(file.path).pipe(request.post('localhost:4000/upload'))
I changed post to put and in my upload.js the post method also to put, but it results in the same error.
我将 post 更改为 put,在我的 upload.js 中也将 post 方法更改为 put,但它导致相同的错误。
My Goal is to upload a file from the html page to localhost:3000/upload which pipes the file to localhost:4000/upload (ideally with same filename) .But I dont get it working (this postdoesn't helped me).
我的目标是将文件从 html 页面上传到 localhost:3000/upload ,该文件将文件通过管道传输到 localhost:4000/upload (理想情况下具有相同的文件名)。但我没有让它工作(这篇文章对我没有帮助)。
app.js:
应用程序.js:
var express = require('express')
, multiparty = require('multiparty')
, request = require('request')
, fs = require('fs')
, util = require('util')
, http = require('http');
var app = express();
app.use('/static', express.static('static'));
process.on('uncaughtException', function (err) {
console.log(err);
});
app.get('/', function (req, res) {
res.redirect('static/index.html');
});
app.post('/upload', function(req, res, next){
//https://github.com/request/request#streaming
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
form.on('file', function(name,file) {
//stream it to localhost:4000 with same name
fs.createReadStream(file.path).pipe(request.post('localhost:4000/upload'))
console.log(file.path);
});
});
var server = app.listen(3000, '0.0.0.0' ,function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
index.html:
索引.html:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Upload</title>
</head>
<body>
<h2>Upload</h2>
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" id="file" name="file" />
<button>upload</button>
</form>
</body>
</html>
upload.js:
上传.js:
var express = require('express')
, multiparty = require('multiparty')
, cors = require('cors')
, util = require('util')
, app = express();
app.use(cors());
process.on('uncaughtException', function (err) {
console.log(err);
});
app.get('/', cors(), function(req, res, next){
res.json({msg: 'This is CORS-enabled for all origins!'});
});
app.post('/upload', cors(), function(req, res, next){
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
form.on('file', function(name,file) {
console.log(file);
console.log(name);
});
});
app.listen(4000, function(){
console.log('CORS-enabled web server listening on port 4000');
});
采纳答案by kmandov
Updated
更新
I believe you're missing the protocol from the url.
It should work, if you add the httpprotocol to the url:
我相信您缺少 url 中的协议。如果您将http协议添加到 url ,它应该可以工作:
fs.createReadStream(file.path).pipe(request.post('http://localhost:4000/upload'))
Make Upload work
使上传工作
When you pipe the file contents to the POST function in upload.js, the multipart form data is lost. You need to create a new POST request and pass the original file contents.
当您将文件内容通过管道传输到 upload.js 中的 POST 函数时,多部分表单数据将丢失。您需要创建一个新的 POST 请求并传递原始文件内容。
Do the following in app.js:
在中执行以下操作app.js:
form.on('file', function(name, file) {
var formData = {
file: {
value: fs.createReadStream(file.path),
options: {
filename: file.originalFilename
}
}
};
// Post the file to the upload server
request.post({url: 'http://localhost:4000/upload', formData: formData});
}
This will also pass the original filename. For more information see: https://github.com/request/request#multipartform-data-multipart-form-uploads
这也将传递原始文件名。有关更多信息,请参阅:https: //github.com/request/request#multipartform-data-multipart-form-uploads
回答by jameslk
I had a similar problem but I wanted to stream the file directly to the remote server instead of saving it locally first. Here's my modifications to get streaming to work:
我遇到了类似的问题,但我想将文件直接流式传输到远程服务器,而不是先将其保存在本地。这是我为了让流媒体工作而进行的修改:
app.post('/upload', function(request, response, next) {
var form = new multiparty.Form();
form.on('part', function(formPart) {
var contentType = formPart.headers['content-type'];
var formData = {
file: {
value: formPart,
options: {
filename: formPart.filename,
contentType: contentType,
knownLength: formPart.byteCount
}
}
};
requestJs.post({
url: 'http://localhost:4000/upload',
formData: formData,
// These may or may not be necessary for your server:
preambleCRLF: true,
postambleCRLF: true
});
});
form.on('error', function(error) {
next(error);
});
form.on('close', function() {
response.send('received upload');
});
form.parse(request);
});
回答by HydraOrc
You actually can do stream.pipe(request.post(url));, and then on the another server your reqvariable will have a stream-like behavior, so you should be able to req.pipe(fs.createWriteStream(path));.
您实际上可以这样做stream.pipe(request.post(url));,然后在另一台服务器上您的req变量将具有类似流的行为,因此您应该能够req.pipe(fs.createWriteStream(path));.
Use req.paramson your route to preserve the filename.
req.params在您的路线上使用以保留文件名。
Example code for server one (use some hashing like md5 to validate your request):
服务器一的示例代码(使用一些像 md5 这样的散列来验证您的请求):
const stream = fs.createReadStream(path);
const md5 = crypto.createHash('md5')
.update(`${filename}${secret}`)
.digest('hex').toUpperCase();
const url = `http://${host}/upload/${md5}/${filename}`;
const r = request.post(url, (err, resp, body) => {});
stream.pipe(r);
Example code for server two:
服务器 2 的示例代码:
router.post('/upload/:md5/:filename', function(req, res, next) {
const { md5, filename } = req.params;
const check = crypto.createHash('md5')
.update(`${filename}${secret}`)
.digest('hex').toUpperCase();
if (md5 !== check) {
res.writeHead(403);
res.end('403');
return;
}
req.pipe(fs.createWriteStream(filename));
req.on('end', next);
});

