在 XHR 中使用 multipart/form-data 作为 Content-Type 时收到“400 Bad Request”

问题描述 投票:0回答:2

我有一个发送一些数据的 AJAX 请求。数据遵循多部分/表单数据规范

我面临的问题是浏览器将Content-Type标头设置为text/plain,它应该是multipart/form-data。

我尝试这样做:

request.setRequestHeader("Content-Type", "multipart/form-data");
但这会给出 400 Bad Request 错误。

如果我这样做

request.setRequestHeader("Content-Typexxxx", "multipart/form-data");
没有错误,“Content-Typexxxx”标头已设置,但显然对我没有帮助。

我猜有一个可以设置的有效内容类型标头列表,并且“multipart/form-data”不在其中,但我找不到解决我的困境的方法。

实际发送的数据示例:

内容类型:多部分/表单数据;边界=l3iPy71otz

--l3iPy71otz
内容处置:表单数据;名称=“titluPublic”

变体_1
--l3iPy71otz
内容处置:表单数据;名称=“nr_versiune”


--l3iPy71otz--

谢谢!

javascript ajax header http-headers xmlhttprequest
2个回答
7
投票

您没有在请求标头中设置

boundary
,如下所示:

request.setRequestHeader("Content-Type", "multipart/form-data; boundary=l3iPy71otz");

有关更多信息,请参阅RFC 2045

5 内容类型标头字段
[…]
参数是媒体的修饰符 子类型,因此不 从根本上影响事物的本质 内容。有意义的一组 参数取决于媒体类型 和子类型。大多数参数是 与单个特定的 亚型。然而,给定 顶级媒体类型可以定义 适用于的参数 该类型的任何子类型。参数 可能需要他们的定义 内容类型或子类型或者它们可能是 选修的。 MIME 实现必须 忽略其名称的任何参数 不认识。

例如“字符集” 参数适用于任何子类型 “文本”,而 “边界” 任何子类型都需要参数 “多部分”媒体类型。

更新:我在网络上发现的另一个问题出现在请求头中的charset

添加到
Content-type
中,但不在正文中的消息边界中时(这对于您的测试用例也是如此) )。这似乎不是一个可能的解决方案,但也许有帮助。

在您的情况下,请在请求标头和消息边界中显式添加

charset

data.params += "--" + data.uniqid + "; charset=UTF-8" + data.crlf; … request.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + data.uniqid + "; charset=UTF-8");

更新2:在本地尝试此操作后,我注意到前导边界未被识别为这样,而是被解释为最后一个参数内容(在我更宽容的服务器上)。也许这导致 Apache 抛出 400 Bad Request

 错误。

经过一番尝试和错误,我注意到这是因为服务器期望

charset

位于
每个边界,甚至是最后一个边界。为了防止混淆,我决定在请求标头中将 charset
 明确设置在边界参数之前
,以便边界将是 Content-type 请求标头中的最后一个参数。之后,一切似乎都很顺利。

data.params = "Content-Type: multipart/form-data; boundary=" + data.uniqid; … data.params += "--" + data.uniqid + data.crlf; … data.params += "--" + data.uniqid + "--"; … request.setRequestHeader("Content-Type", "multipart/form-data; charset=UTF-8; boundary=" + data.uniqid);



0
投票

[...] DispatcherServlet dispatcherServlet = new DispatcherServlet(webApplicationContext); ServletRegistration.Dynamic registration = servletContext.addServlet(SERVLET_NAME, dispatcherServlet); MultipartConfigElement multiPartConfig = new MultipartConfigElement(getSomeDirectory()); registration.setMultipartConfig(multiPartConfig); [...]

HTH.

© www.soinside.com 2019 - 2024. All rights reserved.