[英]What is wrong with my HttpURLConnection request?
我正在嘗試使用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錯誤的請求響應
首先也是最重要的一點:您不能同時寫入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激活作為獨立庫下載 。 另一種選擇是使用JavaMail庫(特別是其ContentType類)進行解析。
第三,主體部分(邊界之間) 內的Content-Length頭應該使用該文件的長度為一個內容長度。 整個請求正文的Content-Length必須是您編寫的所有內容的長度:邊界,正文部分的標題和文件內容。
好消息是,我認為(盡管我不是很肯定)URLConnection會根據您寫入的字節自動設置請求的整體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)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.