我有一段Java代码将字节数组传输到HTTP服务器:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="
+ myBoundary);
connection.setRequestProperty("Content-Length", 1024);
我使用此代码传输大小大于 1024 的字节数组。效果很好。但实际的HTTP消息(由Wireshark捕获)显示Content-Length的值是实际大小,而不是1024。为什么?
我在HTTP规范中搜索,但没有找到提示。我没有使用任何传输编码或传输编码。
我猜HttpURLConnection
只会用正确的值覆盖Content-Length
标头,因为它知道撒谎是不好的;-)
事实上:在sun.net.www.protocol.HttpURLConnection
的第535-550行,如果合适,设置了Content-Length
。这发生在设置用户指定的标头之后,因此该值将被覆盖。
正确的:如果您传输的数据量与声称的数量不匹配,那么您只会混淆另一端。
检查sun.net.www.protocol.http.HttpURLConnection
的来源似乎有一个受限制的标头列表,并且在调用setRequestProperty
时将被静默忽略。 Content-Length
就是其中之一。不幸的是,这似乎没有记录在案(至少我找不到任何关于此的文档,只有对相关问题的讨论)。
谷歌搜索引入此"功能"的 ChangeSet 中提到的错误 ID (?),似乎此更改是作为对安全漏洞 CVE-2010-3541 和 CVE-2010-3573(此主题的 Redhat 错误)的反应而引入的。
通过将 System 属性sun.net.http.allowRestrictedHeaders
设置为 JVM 启动时true
,可以手动禁用此限制。
这为我解决了:
connection.setFixedLengthStreamingMode(myString.getBytes().length);
conn.setRequestProperty("Content-length", String.valueOf(myString.getBytes().length));
"connection.setFixedLengthStreamingMode(myString.getBytes().length);",然后设置 Content-Length 标头。