HTTP POST 中的各个字段是否有大小限制?
is there a size limit to individual fields in HTTP POST?
我有一个 API 文件上传需要多部分表单提交。但是我有一个客户在写客户端,他的系统无法正确生成 multipart/form-data
请求。他要求我修改我的 API 以在 application/x-www-form-urlencoded
请求中接受文件,文件名在一对 key/value 中,文件内容以 base64 编码,在另一对中 key/value对.
原则上我可以很容易地做到这一点(虽然之后我需要淋浴),但我担心尺寸限制。我们预计生产环境中的文件会相当大:5-10MB,有时高达 20MB。我找不到任何可以告诉我关于表单 POST 内单个 key/value 对数据的长度限制的信息,无论是在规范中(我已经查看过 HTTP spec and the Forms spec)或者在特定的实现中(我的 API 在 Java 应用程序服务器 Jetty 上运行,前面有一个 Apache HTTP 服务器)。
key/value 对形式 POST 中单个值的技术和实际限制是多少?
HttpConfiguration class 存在人为限制和配置。最大键数和请求的最大大小 body 内容。
实际上,这是一个非常糟糕的主意。
您将有一个字符串,它使用每个字符 2 个字节的 Base64 数据。
仅使用 Base64,您就有 33% 的典型开销。
他们还必须对各种特殊字符的 Base64 字符串进行 utf8 urlencode(例如“+”,它在 Base64 中有意义,但 space " " 在 urlencoded 形式中。所以他们需要将“+”编码为“%2B”)。
因此对于 20MB 的文件,您将拥有...
20,971,520 字节的原始数据,在原始 Base64 中表示为 27,892,122 个字符,在进行 urlencode 时使用(平均)29,286,728 个字符,其字符串形式将使用 58,573,455 字节的内存。
Jetty 上的解码过程将采用传入的原始 urlencoded 字节,并在解码 urlencoded 形式之前在字符串中分配 2x 该大小。所以这是一个 58,573,456 的长度 java.lang.String(字符串使用 117,146,912 字节的堆内存,并且不要忘记还保存了 29MB 的字节缓冲区数据!)只是为了将该 Base64 二进制文件解码为 x-www-form-urlencoded 字符串形式.
我会反击并强迫他们正确使用 multipart/form-data
。有很多好的库可以正确地生成 form-data。
如果他们正在使用 Java,请告诉他们使用来自 Apache HttpComponents 项目的 httpmime
库(他们不必 have/use/install Apache Http Client 来使用 httpmime ,它是一个独立的库)。
替代方法
没有什么说你必须使用 application/x-www-form-urlecnoded
或 multipart/form-data
。
通过 application/octet-stream
提供原始上传选项
他们使用 POST
,并且必须包含以下有效请求 headers ...
Connection: close
Content-Type: application/octet-stream
Content-Length: <whatever_size_the_content_is>
Connection: close
表示 http 协议何时完成。
Content-Type: application/octet-stream
表示 Jetty 不会将该内容作为请求参数进行处理,也不会对其应用字符集转换。
需要Content-Length
来保证整个文件是sent/received.
然后将原始二进制字节流式传输给您。
这只是文件内容,如果您有其他信息需要传入(例如文件名),请考虑使用查询参数或自定义请求 header(例如: X-Filename: secretsauce.doc
)
在您的 servlet 上,您只需使用 HttpServletRequest.getInputStream() 来获取这些字节,然后使用 Content-Length
变量来验证您是否收到了整个文件。
您可以选择让他们在请求 header 中提供 SHA1 散列,例如 X-Sha1Sum: bed0213d7b167aa9c1734a236f798659395e4e19
,然后您可以使用它来验证整个文件是否 sent/received正确。
我有一个 API 文件上传需要多部分表单提交。但是我有一个客户在写客户端,他的系统无法正确生成 multipart/form-data
请求。他要求我修改我的 API 以在 application/x-www-form-urlencoded
请求中接受文件,文件名在一对 key/value 中,文件内容以 base64 编码,在另一对中 key/value对.
原则上我可以很容易地做到这一点(虽然之后我需要淋浴),但我担心尺寸限制。我们预计生产环境中的文件会相当大:5-10MB,有时高达 20MB。我找不到任何可以告诉我关于表单 POST 内单个 key/value 对数据的长度限制的信息,无论是在规范中(我已经查看过 HTTP spec and the Forms spec)或者在特定的实现中(我的 API 在 Java 应用程序服务器 Jetty 上运行,前面有一个 Apache HTTP 服务器)。
key/value 对形式 POST 中单个值的技术和实际限制是多少?
HttpConfiguration class 存在人为限制和配置。最大键数和请求的最大大小 body 内容。
实际上,这是一个非常糟糕的主意。
您将有一个字符串,它使用每个字符 2 个字节的 Base64 数据。 仅使用 Base64,您就有 33% 的典型开销。
他们还必须对各种特殊字符的 Base64 字符串进行 utf8 urlencode(例如“+”,它在 Base64 中有意义,但 space " " 在 urlencoded 形式中。所以他们需要将“+”编码为“%2B”)。
因此对于 20MB 的文件,您将拥有...
20,971,520 字节的原始数据,在原始 Base64 中表示为 27,892,122 个字符,在进行 urlencode 时使用(平均)29,286,728 个字符,其字符串形式将使用 58,573,455 字节的内存。
Jetty 上的解码过程将采用传入的原始 urlencoded 字节,并在解码 urlencoded 形式之前在字符串中分配 2x 该大小。所以这是一个 58,573,456 的长度 java.lang.String(字符串使用 117,146,912 字节的堆内存,并且不要忘记还保存了 29MB 的字节缓冲区数据!)只是为了将该 Base64 二进制文件解码为 x-www-form-urlencoded 字符串形式.
我会反击并强迫他们正确使用 multipart/form-data
。有很多好的库可以正确地生成 form-data。
如果他们正在使用 Java,请告诉他们使用来自 Apache HttpComponents 项目的 httpmime
库(他们不必 have/use/install Apache Http Client 来使用 httpmime ,它是一个独立的库)。
替代方法
没有什么说你必须使用 application/x-www-form-urlecnoded
或 multipart/form-data
。
通过 application/octet-stream
他们使用 POST
,并且必须包含以下有效请求 headers ...
Connection: close
Content-Type: application/octet-stream
Content-Length: <whatever_size_the_content_is>
Connection: close
表示 http 协议何时完成。Content-Type: application/octet-stream
表示 Jetty 不会将该内容作为请求参数进行处理,也不会对其应用字符集转换。
需要Content-Length
来保证整个文件是sent/received.
然后将原始二进制字节流式传输给您。
这只是文件内容,如果您有其他信息需要传入(例如文件名),请考虑使用查询参数或自定义请求 header(例如: X-Filename: secretsauce.doc
)
在您的 servlet 上,您只需使用 HttpServletRequest.getInputStream() 来获取这些字节,然后使用 Content-Length
变量来验证您是否收到了整个文件。
您可以选择让他们在请求 header 中提供 SHA1 散列,例如 X-Sha1Sum: bed0213d7b167aa9c1734a236f798659395e4e19
,然后您可以使用它来验证整个文件是否 sent/received正确。