在 JavaScript 中为文件上传生成 HTTP 多部分正文 [英] Generating HTTP multipart body for file upload in JavaScript

查看:21
本文介绍了在 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('
');

  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:

火狐:

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

服务器响应为:Error: failed [400] Invalid multipart request with 0 mime parts.

编辑 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--

我收到错误:Error: failed [400] Missing end boundary in multipart body.

推荐答案

修复边界

  1. 如果你定义边界为:BOUNDARY,
  2. 然后每个子部分的开头都标有:--BOUNDARY
  3. 并且消息的结尾标有:--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.

在结束绑定标记后,您可能还需要 ' ' ;).由于 var bodyString = bodyParts.join(' '); 没有将 放在最后一个元素之后,我认为这是必需的.(我们在评论中的讨论表明事实并非如此,所以...)

You probably also need ' ' after ending bondary mark ;). As var bodyString = bodyParts.join(' '); does not put 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 设置不正确(它应该是字节数而不是字符串中的字符数).由于 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 缓冲区,我会尝试使用图像字节:

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天全站免登陆