2016-04-04 9 views
0

私はAndroid上でHttpURLConnectionを使用してサーバーにファイルをPOSTしようとしていますが、getResponseCodeコールはハングして返されません。この問題はファイルがサーバーにとって大きすぎることに起因しているため、サーバーは413というHTTPエラーコードを返します(サーバーログに表示されます)。しかし、私たちのデバイスではこれが受信されないようです。私たちのアプリで次のコードを持っている:HttpURLConnectionのは、応答コードをピックアップしていないようだ、なぜHttpURLConnection getResponseCodeが返されない

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が出力バッファの書き込みを試みたままになっているように見えますが、アプリケーションが出力バッファの書き込みを完了する前に、サーバはすでにレスポンスコードを送信しています(サーバがヘッダーに基づいてPOSTを拒否したため)。サーバーはNode.JSインスタンスへのNginx転送であり、それがまったく役立つならば、ログに413が表示されているので、アプリケーション側の問題だと思う。

int status = httpURLConnection.getResponseCode(); 

答えて

-1

をだから、問題は、応答のいずれかを読む前に全身をアップロードしたいダウンHttpURLConnectionのですが判明:それは次の行にハングアップします。 Nginxは、413の応答を送信し、アプリケーションが本体を送信する前に接続を終了していますが、HttpURLConnectionはまだ本体を送信しようとしています。 Nginx側で接続が閉じられているため、データの送信に失敗しましたが、HttpURLConnectionで指定されたデフォルトのタイムアウトはありません。理想的には、HttpURLConnectionは、出力を書き込もうとしている間に早期レスポンスヘッダーをチェックし、それ以降のAndroidバージョンではこれを行うことができます(4.4でテストしているので、これが後のバージョンでうまくいくかどうかはわかりません)。今のところ、タイムアウトを設定するとうまくいくようです:

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

いいえ、それはありません。サーバーは要求を読み取るまで応答を送信しません。それとは逆の期待は間違っている。 'HttpURLConnection'とは何も関係ありません。 – EJP

+0

サーバーは、本文全体が送信される前に応答を送信しています。つまり、要求からヘッダーを読み取り、本体が大きすぎると判断して応答を送信します。 [この回答を参照](http://stackoverflow.com/a/13424453/1054890) –

+0

@EJPあなたはそのリンクを見ましたか?限り、私の答えは正しいですが、それがない場合は、より良い説明を得るために良いだろう。 –

関連する問題