在JavaScript中生成用于文件上载的HTTP多部分主体 [英] Generating HTTP multipart body for file upload in JavaScript

查看:108
本文介绍了在JavaScript中生成用于文件上载的HTTP多部分主体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在JavaScript中构建HTTP多部分表单数据(在服务器上为Meteor.js HTTP请求)。

I'm trying to build HTTP multipart form data in JavaScript (on the server for Meteor.js HTTP request).

这是发送POST的Meteor代码请求。

Here is the Meteor code that sends POST request.

var res = HTTP.post(url, {
  headers: formatted.headers,
  content: formatted.content
});

我正在使用此代码准备标题和内容。

I'm preparing headers and content using this code.

function MultipartFormData(parts) {
  var boundary = (new Date()).getTime();
  var bodyParts = [];

  _.each(parts, function (value, key) {
    value.data = (new Buffer(value.data)).toString('binary');

    bodyParts.push(
      '---------------------------' + boundary,
      'Content-Disposition: form-data; name="' + key + '"; filename="' + value.filename + '"',
      'Content-Type: ' + value.contentType,
      '',
      value.data);
  });

  bodyParts.push('---------------------------' + boundary + '--', '');

  var bodyString = bodyParts.join('\r\n');

  return {
    content: bodyString,
    headers: {
      'Content-Type': 'multipart/form-data; boundary=' + '---------------------------' + boundary,
      'Content-Length': bodyString.length
    }
  }
}

有关文件的详细信息:

key = 'file'
value.filename = 'file.png'
value.contentType = 'image/png'
value.data is an Uint8Array

服务器无法处理此请求。当我使用标准的Node.js请求对象和使用相同数据的FormBuilder时,一切正常。我只是在两台服务器之间请求http连接。谁能告诉我我的代码有什么问题?我不是HTTP协议的专家,我只有关于生成HTTP请求内容的信息。

Server is unable to process this request. When I'm using standard Node.js request object and FormBuilder using the same data everything work properly. I'm just requesting http connection between two servers. Could anyone tell me what is wrong with my code? I'm not the expert in HTTP protocol and I have only shreds of information about generating HTTP request's content.

还有一件事。我已经尝试将Uint8Array转换为Buffer,ArrayBuffer,String,但它也无效。

And one more thing. I've tried converting Uint8Array to Buffer, ArrayBuffer, String and it also didn't work.

编辑:

我在Firefox和我的应用程序中发送相同文件时测试了什么是http正文:

I've made test what is the http body when sending the same file in Firefox and in my app:

Firefox:

Content-Type: multipart/form-data; boundary=---------------------------19039834425958857471335503868
Content-Length: 299

-----------------------------19039834425958857471335503868
Content-Disposition: form-data; name="file"; filename="test.png"
Content-Type: image/png

PNG


IHDR

·ü]þPLTEÿâ  7
IDAT×cÀÚqÅIEND®B`
-----------------------------19039834425958857471335503868--

我的应用程序:

Content-Type: multipart/form-data; boundary=---------------------------1408816255735
Content-Length: 263

---------------------------1408816255735
Content-Disposition: form-data; name="file"; filename="test.png"
Content-Type: image/png

PNG


IHDR

·ü]þPLTEÿâ      7
IDA×cÀ
                                 ÚqÅIEND®B`
---------------------------1408816255735--

它有点不同但我不知道这种差异的来源是什么。

It differs a little bit but I don't know what is the source of this difference.

编辑2

服务器响应为:错误:失败[400]无效的多部分请求,包含0个mime部分。

编辑3

生成这样的正文时:

Content-Type: multipart/form-data; boundary=1408827490794
Content-Length: 213

--1408827490794
Content-Disposition: form-data; name="file"; filename="test.png"
Content-Type: image/png

PNG


IHDR

·ü]þPLTEÿâ  7
IDA×cÀ
      ÚqÅIEND®B`
--1408827490794--

我收到错误:错误:失败[400]多部分正文中缺少结束边界。

推荐答案

修复边界


  1. 如果将边界定义为: BOUNDARY

  2. 然后每个子部分的开头都标有: - BOUNDARY

  3. 并且消息的结尾标有: - BOUNDARY -

  1. If you define boundary as: BOUNDARY,
  2. then the beginning of each subpart is marked with: --BOUNDARY
  3. and the end of message is marked with: --BOUNDARY--

您的边界定义为

Content-Type: multipart/form-data; boundary=---------------------------1408816255735

所以边界字符串是: --------------------------- 1408816255735 ,已经有28 - (如果我计算得当),所以分隔符应为 - +边界字符串,(不是只是边界字符串)。

So the boundary string is: ---------------------------1408816255735, which already has 28 - (If I counted properly), So the divider should be -- + the boundary string, (not "just the boundary string").

我会摆脱开销 ----------------------- ---- 因为如果添加了前面的 - ,它就会模糊不清。

I would get rid of overhead --------------------------- as it obscures if this preceding -- is added or not.

Content-Type: multipart/form-data; boundary=1408816255735

...

--1408816255735
Content-Disposition: form-data; name="file"; filename="test.png"

...

--1408816255735--

多部分主体中缺少结束边界错误

正如您所说,修复边界后的问题是:多部分中缺少结束边界正文

As you say the problem after fixing boundary is: Missing end boundary in multipart body.

结束债券标记后,您可能还需要'\\\\ n';)。由于 var bodyString = bodyParts.join('\\\\'n'); 没有将\\\\ n放在最后一个元素之后,我想是需要。 (我们在评论中的讨论表明,情况并非如此,所以...)

You probably also need '\r\n' after ending bondary mark ;). As var bodyString = bodyParts.join('\r\n'); does not put \r\n the after the last element, which I suppose is required. (Our discussion in comments showed that the this is not that case, so...)

...所以我怀疑Content-Length是固有的(它应该是是字节数而不是字符串中的字符数)。由于不需要内容长度 - 也许没有它也可以尝试。 (在这种情况下,这恰好是正确的猜测)。

...so I suspect that Content-Length is set incorectly (it should be the byte count not character's count in string). As Content-Length is not required - maybe try without it. (And this happened to be the right guess in this case).

二进制数据

好的,直到现在我们修复了给定代码中的错误。正如您现在所说,多部分请求已成功解析但在尝试将发送的数据解释为PNG图像时出现服务器错误。

Ok until now we fixed mistakes in given code. As you say now the multipart request is parsed successfully but You get server error when it tries to interpret sent data as PNG image.

我不知道如何获取二进制数据 - 没有代码。假设你在循环中的partd value.data 是nodejs Buffer with image bytes我会尝试:

I do not know how you get binary data - there is no code for that. Assuming that in your loop over partd value.data is nodejs Buffer with image bytes I would try with:

_.each(parts, function (value, key) {
    bodyParts.push(
        '--' + boundary,
        'Content-Disposition: form-data; name="' + key + '"; filename="' + 
                value.filename + '"',
        'Content-Transfer-Encoding: base64',
        'Content-Type: ' + value.contentType,
        '',
        value.data.toString('base64'));
});

这篇关于在JavaScript中生成用于文件上载的HTTP多部分主体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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