【问题标题】:How should I decode the contents of a file to include it in a multipart/form-data POST request?我应该如何解码文件的内容以将其包含在 multipart/form-data POST 请求中?
【发布时间】:2020-09-22 15:15:18
【问题描述】:

我必须手动为多部分/表单数据 POST 请求构建正文。我理解结构很好,我可以成功上传不包含文件的表单。我有一个文件作为File 对象,我需要将文件的内容解释为字符串以将它们包含在请求的正文中。我遇到的所有带有文件的多部分表单数据的示例都只有类似 "contents of file go here" 的内容,其中包含文件,并且从不讨论如何从文件获取到字符串。 this 问题的最佳答案接近我正在寻找的内容,但我更愿意避免 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,
            },
        })

【问题讨论】:

  • 您是如何提交表单的?你说I cannot use FormData in production——那么你可以在生产中使用什么?为什么不能使用 FormData?
  • 我必须支持 IE 11,我的环境中有一些东西超出了我的控制范围,导致 polyfill 行为不端。我正在从表单中检索信息并自己打包。
  • 对于电子邮件的多部分表单,我将图像保存到一个目录,然后使用电子邮件正文中的完整路径从该目录引用文件。
  • 感谢@SJacks,但我在浏览器环境中工作。

标签: javascript multipartform-data


【解决方案1】:

4.10.21.7 多部分表单数据多部分/表单数据编码算法,给定条目列表和编码,如下:

设结果为空字符串。

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

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

使用 RFC 描述的规则对(现在已变异的)条目列表进行编码 7578,从表单返回值:multipart/form-data,并返回 产生的字节流。 [RFC7578]

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

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

生成的 multipart/form-data 资源的部分 对应非文件字段一定不能有Content-Type头 指定的。它们的名称和值必须使用字符进行编码 上面选择的编码。

生成的 multipart/form-data 资源中包含的文件名(如 部分文件字段)必须使用上面选择的字符编码, 尽管必要时可能会近似准确的名称(例如 可以从文件名中删除换行符,可以将引号更改为 "%22",以及所选字符中不可表达的字符 编码可以替换为其他字符)。

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

有关如何解释 multipart/form-data 负载的详细信息,请参阅 RFC 7578. [RFC7578] -- HTML: The Living Standard

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

【讨论】:

    猜你喜欢
    • 2019-04-27
    • 1970-01-01
    • 2015-03-28
    • 1970-01-01
    • 2018-07-02
    • 2015-08-27
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    相关资源
    最近更新 更多