我应该如何解码文件的内容以将其包含在多部分/表单数据POST请求中



我必须手动构造多部分/表单数据POST请求的主体。我对结构很理解,我可以成功上传一个不包含文件的表单。我有一个文件作为File对象,我需要将文件的内容解释为字符串,以便将它们包含在请求的正文中。我遇到的所有带有文件的多部分表单数据的例子都有类似于"文件的内容转到这里">包括文件的位置,并且从不讨论如何从文件到字符串。这个问题的首要答案接近我想要的,但我更希望避免base64的额外开销,因为我的表单将处理许多文件。我发现

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

适用于简单的pdf,但使用jpeg失败(这里的"失败"意味着我的服务器无法正确解析图像(。

我有一个使用Fetch的FormData实例的工作示例(我不能在生产中使用FormData(。在Chrome开发人员的工具中,我可以获得请求的原始主体,以查看文件的外观。以下是文件的开头:

Content-Disposition: form-data; name="file"; filename="test.jpg"
Content-Type: image/jpeg
ÿØÿî!AdobedÀ    E¿d„¾¤ÿÛ„           
$$''$$53335;;;;;;;;;;

使用file.text(),消息的相同部分看起来像:

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

当文件像这样解码时:

`
--${boundary}
Content-Disposition: form-data; name="file"; filename="${file.name}"
Content-Type: ${file.type}
${String.fromCharCode.apply(null, new Uint8Array(await file.arrayBuffer()))}`
}
result += `

文件的开头看起来是正确的,但比较完整的字符串会发现有一些差异。

我发现了这个

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

在RFC 2388中,但我认为这是指如何通过有线发送请求主体,而不是主体是如何构建的。我觉得我错过了一些核心概念。任何帮助都将不胜感激。

编辑:以下是如何将表单数据发送到我的服务器:

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多部分表单数据给定条目列表和编码的多部分/表单数据编码算法如下:

让result为空字符串。

对于条目列表中的每个条目:

对于条目名称和值中不能使用选定的字符编码表示,替换字符由一个由U+0026 AMPERSAND字符(&(、一个U+0023组成的字符串NUMBER SIGN字符(#(,一个或多个ASCII数字表示以10为底的字符的代码点,最后是一个U+003B(;(。

使用RFC描述的规则对(现在已变异的(条目列表进行编码7578,从窗体返回值:multipart/form数据,并返回得到的字节流。[RFC7578]

条目列表中的每个条目都是一个字段,条目的名称是字段名称,条目的值就是字段值。

零件的顺序必须与条目中字段的顺序相同列表具有相同名称的多个条目必须视为不同字段。

生成的多部分/表单数据资源中对应的非文件字段不得具有Content-Type标头指定。它们的名称和值必须使用字符进行编码上面选择的编码。

生成的多部分/表单数据资源中包含的文件名(如文件字段的一部分(必须使用上面选择的字符编码,尽管如果需要,可以近似精确的名称(例如。换行符可以从文件名中删除,引号可以改为"%22〃;,以及所选字符中无法表达的字符编码可以由其他字符代替(。

用户代理在生成的返回值时使用的边界该算法是多部分/表单数据边界字符串。(此值用于生成表单提交负载的MIME类型由该算法生成。(

有关如何解释多部分/表单数据有效载荷的详细信息,请参阅RFC7578--HTML:生活标准

这肯定回答了我的问题,但我对实现仍然有点困惑。

最新更新