[英]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.