如何从node.js上传文件 [英] how to upload a file from node.js

查看:262
本文介绍了如何从node.js上传文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我查询这个问题时,我发现了很多帖子,但是他们都提到了如何从浏览器上传文件到node.js服务器。我想从node.js代码上传一个文件到另一个服务器。我试图根据我对node.js有限的知识来编写它,但它不起作用。

 函数(data){
var reqdata ='file ='+ data;
var request = http.request({
host:HOST_NAME,
port:HOST_PORT,
path:PATH,
method:'POST',
头文件:{
'Content-Type':'multipart / form-data',
'Content-Length':reqdata.length
}
},function(response){
var data ='';
response.on('data',function(chunk){
data + = chunk.toString();
});
response.on('end',function(){
console.log(data);
});
});

request.write(reqdata +'\r\\\
\r\\\
');
request.end();





$ b

上述函数被其他生成数据的代码调用。 >

我尝试使用curl -Ffile = @< filepath>来上传相同的数据文件上传成功但是我的代码失败了。服务器返回一个应用程序特定的错误,暗示上传的文件无效/损坏。

我收集了tcpdump数据,并在wireshark中进行了分析。从我的node.js代码发送的数据包缺少多部分数据所需的边界。我在wireshark包中看到这个消息

 多部分解析器找不到所需的边界参数。 

任何想法如何在node.js代码中实现这一点?
<解决方案Multipart是相当复杂的,如果你想让它看起来像一个客户端通常处理multipart / form-data,你必须做一些事情。您首先必须选择一个边界键,这通常是一个随机的字符串来标记部分的开始和结束(在这种情况下,因为您要发送单个文件,所以这只是一个部分)。每个部分(或一个部分)将需要一个标题(由边界键初始化),设置内容类型,表单字段的名称和传输编码。一旦零件完成,您需要使用边界键标记每个零件的末端。



我从来没有用过multipart,但我认为这是是如何做到的。有人请纠正我,如果我错了:

  var boundaryKey = Math.random()。toString(16); // random string 
request.setHeader('Content-Type','multipart / form-data; boundary =''+ borderKey +'');
//唯一部分的头(这里需要使用CRLF)
request.write(
' - '+ boundaryKey +'\r\\\
'
//在这里使用你的文件的MIME类型,如果已知
+'Content-Type:application / octet-stream \r\\\
'
//name是表单的名字字段
//filename是原始文件的名称
+'Content-Disposition:form-data; name =my_file; filename =my_file.bin\r\\\
'
+'Content-Transfer-Encoding:binary \r\\\
\r\'
);
fs.createReadStream('./my_file.bin',{bufferSize:4 * 1024})
//在选项中将end设置为false,以便在请求中调用.end() b $ b .pipe(request,{end:false})//也许直接写入套接字?
.on('end',function(){
//标记唯一部分的结尾
request.end(' - '+ boundaryKey +' - ') ;
});

再一次,我从来没有这样做过,但我认为是如何实现的。也许更有知识的人可以提供更多的见解。

如果您想将其作为base64或非原始二进制文件的编码发送,则必须自己完成所有的管道工作。这将变得更加复杂,因为你将不得不暂停阅读流,并等待请求中的流失事件,以确保你没有用完所有的内存(如果它通常不是一个大文件不用担心这个)。实际上,没关系的是,你只能在读取流选项中设置编码。编辑



如果没有一个Node模块已经这样做,我会感到惊讶。也许有人对这个问题有更多的了解可以帮助我们了解底层的细节,但是我认为应该在某个地方有个模块。


I found many posts when I queried for this problem, but they all refer to how to upload a file from your browser to a node.js server. I want to upload a file from node.js code to another server. I tried to write it based on my limited knowledge of node.js, but it doesn't work.

function (data) {
  var reqdata = 'file='+data;
  var request = http.request({
    host : HOST_NAME,
    port : HOST_PORT,
    path : PATH,
    method : 'POST',
    headers : {
      'Content-Type' : 'multipart/form-data',
      'Content-Length' : reqdata.length
    }
  }, function (response) {
      var data = '';
      response.on('data', function(chunk) {
        data += chunk.toString();
      });
      response.on('end', function() {
        console.log(data);
      });
    });

  request.write(reqdata+'\r\n\r\n');
  request.end();
})

The above function is called by other code that generates data.

I tried to upload same data file using curl -F "file=@<filepath>" and the upload is successful. But my code fails. The server returns an application specific error which hints that the uploaded file was invalid/corrupt.

I collected tcpdump data and analysed it in wireshark. The packet sent from my node.js code lacks the boundary required for the multipart data. I see this message in wireshark packet

The multipart dissector could not find the required boundary parameter.

Any idea how to accomplish this in node.js code?

解决方案

Multipart is pretty complex, if you want to make it look like how a client usually handles "multipart/form-data", you have to do a few things. You first have to select a boundary key, this is usually a random string to mark the beginning and end of the parts, (in this case it would be only one part since you want to send a single file). Each part (or the one part) will need a header (initialized by the boundary key), setting the content-type, the name of the form field and the transfer encoding. Once the part(s) are completed, you need to mark the end of each part with the boundary key.

I've never worked with multipart, but I think this is how it could be done. Someone please correct me if I'm wrong:

var boundaryKey = Math.random().toString(16); // random string
request.setHeader('Content-Type', 'multipart/form-data; boundary="'+boundaryKey+'"');
// the header for the one and only part (need to use CRLF here)
request.write( 
  '--' + boundaryKey + '\r\n'
  // use your file's mime type here, if known
  + 'Content-Type: application/octet-stream\r\n' 
  // "name" is the name of the form field
  // "filename" is the name of the original file
  + 'Content-Disposition: form-data; name="my_file"; filename="my_file.bin"\r\n'
  + 'Content-Transfer-Encoding: binary\r\n\r\n' 
);
fs.createReadStream('./my_file.bin', { bufferSize: 4 * 1024 })
  // set "end" to false in the options so .end() isnt called on the request
  .pipe(request, { end: false }) // maybe write directly to the socket here?
  .on('end', function() {
    // mark the end of the one and only part
    request.end('--' + boundaryKey + '--'); 
  });

Again, I've never done this before, but I think that is how it could be accomplished. Maybe someone more knowledgable could provide some more insight.

If you wanted to send it as base64 or an encoding other than raw binary, you would have to do all the piping yourself. It will end up being more complicated, because you're going to have to be pausing the read stream and waiting for drain events on the request to make sure you don't use up all your memory (if it's not a big file you generally wouldn't have to worry about this though). EDIT: Actually, nevermind that, you could just set the encoding in the read stream options.

I'll be surprised if there isn't a Node module that does this already. Maybe someone more informed on the subject can help with the low-level details, but I think there should be a module around somewhere that does this.

这篇关于如何从node.js上传文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆