我正在尝试使用PUT请求调用REST API,但是我收到了400错误代码(错误请求)。有人可以发现我可能在做错什么吗?
我已经使用REST客户端成功调用了此API,以下是使用的标头和正文:
https://imgur.com/dZVyawn https://imgur.com/lMtn2JB
String credentials = Base64.getEncoder().encodeToString(("wcadmin:wcadmin").getBytes());
URL url = new URL(getURL());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("PUT");
connection.setDoOutput(true);
connection.setDoInput(true);
//Set Headers
String fileUrl = "c:\\0000000050.xml";
File fileToUpload = new File(fileUrl);
long length = fileToUpload.length();
String FORM_DATA_BOUNDARY = "------FormBoundary" + System.currentTimeMillis();
connection.setRequestProperty("csrf_nonce", getNonceValue());
connection.setRequestProperty("Accept", "application/xml");
connection.setRequestProperty("Authorization", "Basic " + credentials);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + FORM_DATA_BOUNDARY);
connection.setRequestProperty("Content-Length", Long.toString(length));
//Setup Request Body Writer
OutputStream requestBodyOutputStream = connection.getOutputStream();
BufferedWriter requestBodyWriter = new BufferedWriter(new OutputStreamWriter(requestBodyOutputStream));
//Write Body
requestBodyWriter.write("\r\n\r\n");
requestBodyWriter.write(FORM_DATA_BOUNDARY);
requestBodyWriter.write("\r\n");
requestBodyWriter.write("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileUrl + "\"");
requestBodyWriter.write("\r\n");
requestBodyWriter.write("Content-Type: text/xml");
requestBodyWriter.write("\r\n\r\n");
requestBodyWriter.flush();
FileInputStream uploadFileStream = new FileInputStream(fileToUpload);
int bytesRead;
byte[] dataBuffer = new byte[1024];
while ((bytesRead = uploadFileStream.read(dataBuffer)) != -1) {
requestBodyOutputStream.write(dataBuffer, 0, bytesRead);
}
requestBodyOutputStream.flush();
requestBodyWriter.write("\r\n");
requestBodyWriter.write(FORM_DATA_BOUNDARY);
requestBodyWriter.flush();
//Close the streams
requestBodyOutputStream.close();
requestBodyWriter.close();
uploadFileStream.close();
//Read Response
String inputLine;
StringBuffer content = new StringBuffer();
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
BufferedReader responseReader = new BufferedReader(new InputStreamReader(inputStream));
if (responseReader != null) {
while ((inputLine = responseReader.readLine()) != null) {
content.append(inputLine);
}
responseReader.close();
}
}
connection.disconnect();
收到错误400错误的请求响应
答案 0 :(得分:0)
第一个也是最重要的一点:您不能同时写入OutputStream和包装相同的OutputStream的OutputStreamWriter。他们会互相冲突。
完全不使用OutputStreamWriter;而是自己将文本转换为字节:
OutputStream requestBodyOutputStream = connection.getOutputStream();
requestBodyOutputStream.write("\r\n\r\n".getBytes(StandardCharsets.UTF_8));
requestBodyOutputStream.write(FORM_DATA_BOUNDARY.getBytes(StandardCharsets.UTF_8));
// etc.
第二,您正在使用系统的默认字符集在字节和字符串之间进行转换,这意味着确切地编写的内容取决于运行代码的系统。在未指定显式字符集的情况下,请勿调用String.getBytes。通常getBytes(StandardCharsets.UTF_8)
是您想要的。
类似地,您需要将一个Charset传递到InputStreamReader的创建中(尽管这不是问题的根源,因为您目前没有收到有效的回复)。不要假设一个字符集;使用响应的Content-Type标头中的charset
MIME类型参数。如果您使用的Java版本早于11,则可以使用javax.activation.MimeType类解析Content-Type值,但是请注意,从Java 11开始,javax.activation软件包已从Java SE中删除。对于Java 11及更高版本,将Java Activation can be downloaded作为独立库。另一种选择是使用JavaMail库(特别是其ContentType类)进行解析。
第三,正文部分(边界之间)的内容长度标头 应该使用文件的长度作为内容长度。 整个请求正文的Content-Length必须是您编写的所有内容的长度:边界,正文部分标题和文件内容。
一个好消息是,我认为(尽管我不是很肯定)URLConnection会根据您写入的字节数自动设置请求的整体Content-Length,因此您可能不需要自己计算长度;您可以根本不用设置“ Content-Length”。
当您传递正确的请求时,您会发现您正在响应中删除换行符。如果响应应该是人类可读的文本,则这些换行符可能很重要。如果您使用的是Java 10或更高版本,则可以将Reader.transferTo与StringWriter结合使用:
StringWriter responseBody = new StringWriter();
responseReader.transferTo(responseBody);
String content = responseBody.toString();
如果您使用的Java版本低于10:
new BufferedReader
不能返回null,因此检查null是没有意义的。在Java中,new
运算符无论如何都会始终返回一个新对象(除非引发异常,在这种情况下,new
根本不会返回)。您正在将文件复制到请求中,而没有任何缓冲,这将很慢且效率低下。考虑改用Files.copy(fileToUpload.toPath(), requestBodyOutputStream)
。