簡體   English   中英

HttpURLConnection getResponseCode 不返回

[英]HttpURLConnection getResponseCode not returning

我正在嘗試使用 Android 上的 HttpURLConnection 將文件發布到我們的服務器,但 getResponseCode 調用只是掛起並且永遠不會返回。 問題源於文件對於服務器來說太大,因此服務器發回 HTTP 錯誤代碼 413(我可以在服務器日志中看到),但在我們的設備上,似乎從未收到過。 我的應用程序中有以下代碼:

public FileUploadUtility(URL requestURL, File uploadFile) throws IOException
{
    file = uploadFile;
    String fileName = uploadFile.getName();

    httpURLConnection = (HttpURLConnection) requestURL.openConnection();
    httpURLConnection.setUseCaches(false);
    httpURLConnection.setDoOutput(true);
    httpURLConnection.setDoInput(true);
    httpURLConnection.setRequestMethod("POST");
    httpURLConnection.setRequestProperty("Content-Type", URLConnection.guessContentTypeFromName(fileName));
    //httpURLConnection.setRequestProperty("Content-Length", Long.toString(fileSize));
    long fileSize = uploadFile.length();
    httpURLConnection.setFixedLengthStreamingMode(fileSize);
    outputStream = httpURLConnection.getOutputStream();
}

/**
 * Completes the request and receives response from the server.
 *
 * @return a list of Strings as response in case the server returned
 * status OK, otherwise an exception is thrown.
 * @throws IOException
 */
public String finish(ProgressListener progressListener) throws IOException, HTTPErrorCodeException
{
    try (FileInputStream inputStream = new FileInputStream(file))
    {
        byte[] buffer = new byte[100 * 1024];
        int bytesRead;

        long fileSize = file.length();
        int total = 0;
        while ((bytesRead = inputStream.read(buffer)) != -1)
        {
            outputStream.write(buffer, 0, bytesRead);

            total += bytesRead;
            if(fileSize > 0)
            {
                progressListener.fileUploadProgress((float)total / (float)fileSize);
            }
        }
        outputStream.flush();
    }
    catch (Exception e)
    {
        e.printStackTrace();
        throw new IOException("Error uploading file: " + e.getMessage());
    }

    String response;

    // Checks server's status code first
    int status = httpURLConnection.getResponseCode();
    if (status == HttpURLConnection.HTTP_OK)
    {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())))
        {
            StringBuilder builder = new StringBuilder();
            String output;
            while ((output = reader.readLine()) != null)
            {
                builder.append(output);
            }
            response = builder.toString();
            Log.i("Server response body", response);
        }
        httpURLConnection.disconnect();
        httpURLConnection = null;
    }
    else
    {

        String serverResponseMessage = httpURLConnection.getResponseMessage();
        Log.i("Server Response Message", serverResponseMessage);

        try (BufferedReader responseReader = new BufferedReader(new InputStreamReader((httpURLConnection.getInputStream()))))
        {
            StringBuilder builder = new StringBuilder();
            String output;
            while ((output = responseReader.readLine()) != null)
            {
                builder.append(output);
            }
            Log.i("Server response body", builder.toString());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        try (BufferedReader errorReader = new BufferedReader(new InputStreamReader((httpURLConnection.getErrorStream()))))
        {
            StringBuilder builder = new StringBuilder();
            String output;
            while ((output = errorReader.readLine()) != null)
            {
                builder.append(output);
            }
            Log.i("Server error", builder.toString());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        throw new HTTPErrorCodeException(status);
    }

    return response;
}

重申一下,問題不在於“為什么服務器拒絕上傳”,而是 HttpURLConnection 似乎沒有獲取響應代碼的原因。 闖入調試器時,看起來 HttpURLConnection 在嘗試寫入 output 緩沖區時被卡住了,但在應用程序完成寫入 output 緩沖區之前,服務器已經發送了響應代碼(因為服務器已根據標頭拒絕 POST)。 服務器是 Nginx 轉發到 Node.JS 實例,如果這有幫助的話,但我可以在日志中看到 413,我認為這是應用程序方面的問題。 它掛在以下行:

int status = httpURLConnection.getResponseCode();

所以事實證明問題出在 HttpURLConnection 想要在閱讀任何響應之前上傳整個正文。 Nginx 正在發送 413 響應並在應用程序發送正文之前關閉連接,但 HttpURLConnection 仍在嘗試發送正文。 由於連接在 Nginx 端關閉,發送數據失敗,但 HttpURLConnection 沒有指定默認超時。 理想情況下, HttpURLConnection 會在嘗試寫入輸出時檢查早期響應標頭,並且它可能會在以后的 Android 版本中執行此操作(我正在 4.4 上進行測試,因此我不確定這在以后的版本中是否更有效)。 目前,設置超時似乎有效:

httpURLConnection.setConnectTimeout(10 * 1000);
httpURLConnection.setReadTimeout(10 * 1000);

使用模擬器時也出現了同樣的問題。 我重新啟動了模擬器,問題就消失了。

這樣做: 這個答案

暫無
暫無

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

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