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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4773725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:01:26  来源:igfitidea点击:

Getting '400 Bad Request' when using multipart/form-data as Content-Type in XHR

javascriptajaxheaderhttp-headersxmlhttprequest

提问by Sorin Buturugeanu

I have an AJAX request that sends out some data. The data respects the multipart/form-data specification.

我有一个发送一些数据的 AJAX 请求。数据遵守 multipart/form-data规范

The problem I'm facing is that the browser sets the Content-Type header to text/plain and it should be multipart/form-data.

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

I've tried doing this: request.setRequestHeader("Content-Type", "multipart/form-data");but this gives out an 400 Bad Request error.

我试过这样做:request.setRequestHeader("Content-Type", "multipart/form-data");但这给出了 400 Bad Request 错误。

If I do request.setRequestHeader("Content-Typexxxx", "multipart/form-data");there is no error, the "Content-Typexxxx" header is set but it obviously is no help to me.

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

I guess there is a list of valid Content-Type headers one can set and "multipart/form-data" isn't among them, but I cannot find a sollution to my predicament.

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

Sample of the data actually being sent:

实际发送的数据示例:

Content-Type: multipart/form-data; boundary=l3iPy71otz

--l3iPy71otz
Content-Disposition: form-data; name="titluPublic"

Variation_1
--l3iPy71otz
Content-Disposition: form-data; name="nr_versiune"


--l3iPy71otz--

Thanks!

谢谢!

回答by Marcel Korpel

You didn't set the boundaryin your request header, as in:

您没有boundary在请求标头中设置 ,如下所示:

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

For more information, see RFC 2045:

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

5 Content-Type Header Field
[…]
Parameters are modifiers of the media subtype, and as such do not fundamentally affect the nature of the content. The set of meaningful parameters depends on the media type and subtype. Most parameters are associated with a single specific subtype. However, a given top-level media type may define parameters which are applicable to any subtype of that type. Parameters may be required by their defining content type or subtype or they may be optional. MIME implementations must ignore any parameters whose names they do not recognize.

For example, the "charset" parameter is applicable to any subtype of "text", while the "boundary" parameter is required for any subtype of the "multipart" media type.

5 Content-Type Header Field
[…]
参数是媒体子类型的修饰符,因此不会从根本上影响内容的性质。一组有意义的参数取决于媒体类型和子类型。大多数参数与单个特定子类型相关联。然而,给定的顶级媒体类型可以定义适用于该类型的任何子类型的参数。参数可能是其定义内容类型或子类型所必需的,也可能是可选的。MIME 实现必须忽略其名称无法识别的任何参数。

例如,“charset”参数适用于“text”的任何子类型,而“boundary”参数适用于“multipart”媒体类型的任何子类型。

Update:Another problem I found on the netappears when a charsetis added to the Content-typein the request header, but not in the message boundaries in the body (this is also true for your test case). It doesn't seem a likely solution, but perhaps it helps.

更新:在网上发现的另一个问题出现在将 acharset添加到Content-type请求标头中时,而不是在正文中的消息边界中(这对于您的测试用例也是如此)。这似乎不是一个可能的解决方案,但也许它有帮助。

In your case, explicitly add a charsetto both the request header and in the message boundaries:

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

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

Update 2:After trying this myself locally, I noticed the leading boundary wasn't recognized as such, but interpreted as the last parameter contents (on my more forgiving server). Perhaps that was causing Apache to throw a 400 Bad Requesterror.

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

After some trial and error, I noticed that that was caused because the server expected the charsetto be in everyboundary, even the last one. To prevent confusion, I decided to explicitly set the charsetin the request header beforethe boundary parameter, so that the boundary would be the last parameter in the Content-typerequest header. After this, everything seemed to work fine.

经过一些试验和错误,我注意到这是因为服务器期望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);