Java的HttpURLConnection似乎在请求中附加了0018字符?

时间:2018-12-15 15:18:33

标签: java http multipartform-data

我正在尝试通过HTTP发送图像。

我已经通过Chrome使用Wireshark进行了测试,以查看请求的详细信息。标头和多部分内容之间的分隔为\r\n

但是,我在Java中的实现似乎与\r\n和字符0018分开,根据FileFormat.info,字符为CANCEL

我正在使用Java's HttpURLConnection(可以从Kotlin访问,但这不应该是问题),这是用于写入文件内容的代码示例:

val endl = "\r\n"
val hyphens = "--"
val boundary = "----${System.currentTimeMillis()}---"

// conn is an HttpURLConnection
val output = conn.outputStream
val writer = DataOutputStream(output)
writer.flush()

writer.writeUTF(hyphens + boundary + endl) // first time writing
writer.writeUTF("Content-Disposition: form-data; name: [REDACTED]" + endl)
writer.writeUTF("Content-Type: [REDACTED]" + endl)
writer.writeUTF(endl)

// [REDACTED: Writing the contents of the file]

writer.writeUTF(endl)
writer.writeUTF(hyphens + boundary + hyphens + endl)

writer.flush()
writer.close()

(此示例的完整代码可以在here,第99-144行中找到)

字符0018插入在该代码示例之前,并且紧接在标头(使用HttpURLConnection.setRequestProperty编写的标头之后),所以我不认为它们可能是问题……以防万一,您可以在第here行第64-91行中找到该代码。

这是请求正文的开头:

------1544883782650---
DContent-Disposition: form-data; name: "avatar"; filename: "wf.png"
Content-Type: image/png

(您可以在第一行的开头,就在边界之前看到CANCEL字符)。

与Chrome的请求相比:

------WebKitFormBoundaryAhYDuYuz5IuXB95v
Content-Disposition: form-data; name="avatar"; filename="discord.png"
Content-Type: image/png

由于某些原因,Chrome没有这些奇怪的字符。

注意。我只是注意到Chrome使用form-data; name="avatar"; filename="discord.png",而我使用form-data; name: "avatar"; filename: "wf.png";我编辑并重新测试,这不是问题。

2 个答案:

答案 0 :(得分:1)

从Javadoc https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html#writeUTF-java.lang.String-开始,重点是:

  

首先,将两个字节写入到输出流中,就像通过writeShort方法给出要跟随的字节数一样。该值是实际写入的字节数,而不是字符串的长度。按照长度,使用修改后的字符的UTF-8编码,依次输出字符串的每个字符。 ...

Data{Input,Output}Stream不适用于文本,也不应该用于文本。尽管HTTP是不可知的(尽管它同时支持文本和二进制),但MIME总体上来说(尤其是多部分)通常是文本,或者至少是文本兼容的,以使其与传统上是文本的电子邮件兼容。

答案 1 :(得分:1)

writeUTF的{​​{3}}说:

  

首先,将两个字节写入输出流,就像通过writeShort方法给出要跟随的字节数一样。该值是实际写入的字节数,而不是字符串的长度。按照该长度,使用修改后的字符的UTF-8编码,依次输出字符串的每个字符。

在每一行的开头看到的可能是2个字符,它们表示要跟随的字节数。

我认为DataOutputStream对于您的用例而言并不理想。用write(byte[] bytes)转换标题OutputStream后,请使用String的普通s.getBytes("UTF-8")方法。