簡體   English   中英

我的HttpURLConnection請求出了什么問題?

[英]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根本不會返回)。
  • 您應該使用StringBuilder,而不是StringBuffer。 它們是相同的,只是StringBuffer是一個較舊的類,它為每種方法提供線程安全性,從而幾乎為所有用例帶來不必要的開銷。

您正在將文件復制到請求中而沒有任何緩沖,這將很慢且效率低下。 考慮改用Files.copy(fileToUpload.toPath(), requestBodyOutputStream)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM