简体   繁体   English

我应该如何解码文件的内容以将其包含在 multipart/form-data POST 请求中?

[英]How should I decode the contents of a file to include it in a multipart/form-data POST request?

I'm in a situation where I have to construct the body for a multipart/form-data POST request manually.我处于必须手动为 multipart/form-data POST 请求构造正文的情况。 I understand the structure just fine, and I can successfully upload a form that does not include files.我对结构的理解很好,我可以成功上传不包含文件的表单。 I have a file as a File object and I need to interpret the contents of the file as a string to include them in the body of the request.我有一个File object 文件,我需要将文件的内容解释为一个字符串,以将它们包含在请求的正文中。 All the examples I have come across of multipart form data with files just have something like "contents of file go here" where the file is included and never discuss how to get from file to string.我遇到的所有包含文件的多部分表单数据的示例都包含类似“此处文件 go 的内容”之类的内容,其中包含文件,从不讨论如何从文件获取字符串。 The top answer for this question comes close to what I'm looking for, but I'd prefer to avoid the extra overhead of base64 since my form will be handling many files. 这个问题的最佳答案接近我正在寻找的内容,但我宁愿避免 base64 的额外开销,因为我的表单将处理许多文件。 I have found that我发现

`
--${boundary}
Content-Disposition: form-data; name="file"; filename="${file.name}"
Content-Type: ${file.type}

${await file.text()}`

works for a simple pdf but fails with a jpeg (here "fails" means that my server cannot parse the image correctly).适用于简单的 pdf 但因 jpeg 而失败(此处“失败”意味着我的服务器无法正确解析图像)。

I have a working a example using a FormData instance with Fetch (I cannot use FormData in production).我有一个使用FormData实例和 Fetch 的工作示例(我不能在生产中使用FormData )。 In the Chrome developers tools I can get the raw body of the request to see what the file looks like.在 Chrome 开发人员工具中,我可以获得请求的原始主体以查看文件的外观。 Here's what the beginning of the file looks like there:这是文件的开头:

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

ÿØÿî!AdobedÀ    E¿d„¾¤ÿÛ„           
$$''$$53335;;;;;;;;;;

Using file.text() the same portion of the message looks like:使用file.text()消息的相同部分如下所示:

����!Adobed�    E�d������           
$$''$$5333

When the file is decoded like this:当文件像这样解码时:

`
--${boundary}
Content-Disposition: form-data; name="file"; filename="${file.name}"
Content-Type: ${file.type}

${String.fromCharCode.apply(null, new Uint8Array(await file.arrayBuffer()))}`
    }
    result += `

The beginning of the file looks correct but comparing the full strings shows that there are a few differences.文件的开头看起来是正确的,但比较完整的字符串表明存在一些差异。

I found this我找到了这个

4.3 Encoding

   While the HTTP protocol can transport arbitrary binary data, the
   default for mail transport is the 7BIT encoding.  The value supplied
   for a part may need to be encoded and the "content-transfer-encoding"
   header supplied if the value does not conform to the default
   encoding.  [See section 5 of RFC 2046 for more details.]

in RFC 2388, but I believe this is referring to how the request body is sent over-the-wire and not about how the body is constructed.在 RFC 2388 中,但我相信这是指如何通过网络发送请求正文,而不是关于正文的构建方式。 I feel like I'm missing some core concept here.我觉得我在这里缺少一些核心概念。 Any help will be greatly appreciated.任何帮助将不胜感激。

EDIT: Here is how the form data is being sent to my server:编辑:这是将表单数据发送到我的服务器的方式:

        const response = await fetch(url, {
            method: 'POST', // *GET, POST, PUT, DELETE, etc.
            mode: 'cors', // no-cors, *cors, same-origin
            cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
            credentials: 'same-origin', // include, *same-origin, omit
            redirect: 'follow', // manual, *follow, error
            referrer: 'no-referrer', // no-referrer, *client
            body: serializedData, // body data type must match "Content-Type" header
            headers: {
                'Content-Type': 'multipart/form-data; boundary=' + boundary,
            },
        })

4.10.21.7 Multipart form data The multipart/form-data encoding algorithm, given an entry list and encoding, is as follows: 4.10.21.7 多部分表单数据 给定条目列表和编码,多部分/表单数据编码算法如下:

Let result be the empty string.让结果为空字符串。

For each entry in entry list:对于条目列表中的每个条目:

For each character in the entry's name and value that cannot be expressed using the selected character encoding, replace the character by a string consisting of a U+0026 AMPERSAND character (&), a U+0023 NUMBER SIGN character (#), one or more ASCII digits representing the code point of the character in base ten, and finally a U+003B (;).对于无法使用所选字符编码表示的条目名称和值中的每个字符,将字符替换为由 U+0026 AMPERSAND 字符 (&)、U+0023 NUMBER SIGN 字符 (#)、一个或更多的 ASCII 数字表示以十为基数的字符的代码点,最后是 U+003B (;)。

Encode the (now mutated) entry list using the rules described by RFC 7578, Returning Values from Forms: multipart/form-data, and return the resulting byte stream. [RFC7578]使用 RFC 7578,从 Forms 返回值:multipart/form-data,并返回结果字节 stream 中描述的规则对(现在变异的)条目列表进行编码。[RFC7578]

Each entry in entry list is a field, the name of the entry is the field name and the value of the entry is the field value.条目列表中的每个条目都是一个字段,条目的名称是字段名,条目的值是字段值。

The order of parts must be the same as the order of fields in entry list.部分的顺序必须与条目列表中字段的顺序相同。 Multiple entries with the same name must be treated as distinct fields.具有相同名称的多个条目必须被视为不同的字段。

The parts of the generated multipart/form-data resource that correspond to non-file fields must not have a Content-Type header specified.与非文件字段对应的生成的 multipart/form-data 资源部分不得指定Content-Type header。 Their names and values must be encoded using the character encoding selected above.它们的名称和值必须使用上面选择的字符编码进行编码。

File names included in the generated multipart/form-data resource (as part of file fields) must use the character encoding selected above, though the precise name may be approximated if necessary (eg newlines could be removed from file names, quotes could be changed to "%22", and characters not expressible in the selected character encoding could be replaced by other characters).生成的 multipart/form-data 资源中包含的文件名(作为文件字段的一部分)必须使用上面选择的字符编码,但如果需要,可以近似使用精确名称(例如,可以从文件名中删除换行符,可以更改引号到“%22”,并且在所选字符编码中无法表达的字符可以用其他字符替换)。

The boundary used by the user agent in generating the return value of this algorithm is the multipart/form-data boundary string.用户代理在生成该算法的返回值时使用的边界是 multipart/form-data 边界字符串。 (This value is used to generate the MIME type of the form submission payload generated by this algorithm.) (此值用于生成此算法生成的表单提交负载的 MIME 类型。)

For details on how to interpret multipart/form-data payloads, see RFC 7578. [RFC7578] -- HTML: The Living Standard有关如何解释多部分/表单数据有效负载的详细信息,请参阅 RFC 7578。 [RFC7578] -- HTML:生活标准

This definitely answers my question, but I'm still a bit confused on the implementation.这肯定回答了我的问题,但我对实现仍然有点困惑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 axios 在 POST 多部分/表单数据请求中发送文件和 json - sending file and json in POST multipart/form-data request with axios 如何使用 multipart/form-data 发送请求? - how do I send a request using multipart/form-data? 如何将文件发布到多部分/表单数据? - How to post files to a multipart/form-data? 无法弄清楚如何发出 Axios POST 请求,其中包含 Vue.js 中的“multipart/form-data”文件 - Unable to figure out how to make an Axios POST request which contains “multipart/form-data” file in Vue.js 文件上传ajax:您的POST请求的正文格式不正确的multipart / form-data - file upload ajax:The body of your POST request is not well-formed multipart/form-data 在Angular2中构建multipart / form-data POST请求并验证输入类型File - Build multipart/form-data POST request in Angular2 and validate Input type File 节点js POST请求multipart / form-data,如何更改名称属性 - node js POST request multipart/form-data, how to change name attribute POST文件多部分/表单数据(JavaScript)时出错 - Error when POST file multipart/form-data (JavaScript) 错误说POST请求不包含multipart / form-data或multipart / mixed流,即使我明确地定义它 - Error says that POST request doesn't contain a multipart/form-data or multipart/mixed stream even though I explicitly define it as such 强大:解析多部分/表单数据请求,然后上传文件 - Formidable: Parse multipart/form-data request THEN upload file
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM