2016-04-04 25 views
0

Android'de HttpURLConnection kullanarak sunucumuza bir dosya POST yapmaya çalışıyorum, ancak getResponseCode çağrısı yalnızca kilitleniyor ve hiçbir zaman geri dönmez. Sorun, sunucu için çok büyük olan dosyadan kaynaklanıyor, bu yüzden sunucu, 413 (sunucu günlüklerinde görebildiğim) bir HTTP hata kodunu geri gönderiyor, ancak bizim cihazımızda, bu hiç alınmadığı gibi görünüyor. Bizim uygulamasında aşağıdaki kodu var:HttpURLConnection getResponseCode dönen değil

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; 
} 

Sadece tekrar etmek gerekirse, HttpURLConnection yanıt kodu almak için görünmüyor neden, bu yüklemeyi reddeden sunucu neden 'var sorun değildir. Hata ayıklayıcısına ayırırken, HttpURLConnection çıktı arabelleğini yazmaya çalışırken sıkışmış gibi görünüyor, ancak uygulama zaten çıktı arabelleği yazma işlemini bitirmeden önce sunucu yanıt kodunu göndermiş (sunucu, POST'u başlığa göre reddetti). Sunucu Nginx bir Node.JS örneğine iletiyor, eğer bu hiç yardımcı olmuyorsa, ancak 413'ü günlüklerde görebildiğim gibi, bunun uygulamanın şeyleri tarafında bir sorun olduğunu düşünüyorum.

int status = httpURLConnection.getResponseCode(); 

cevap

-1

Yani mesele yanıtının herhangi okumadan önce bütün vücudu yüklemek isteyen aşağı HttpURLConnection olduğunu çıkıyor: Bu aşağıdaki satırı üzerinde asılı kalır. Nginx 413 cevabı gönderiyor ve uygulama vücudu göndermeden önce bağlantıyı kapatıyor, ancak HttpURLConnection hala vücudu göndermeye çalışıyor. Bağlantı Nginx ucunda kapalı olduğundan, verilerin gönderilmesi başarısız oluyor, ancak HttpURLConnection tarafından varsayılan zaman aşımı yok. İdeal olarak, HttpURLConnection, çıktıyı yazmaya çalışırken erken yanıt başlıklarını kontrol ederdi ve bunu daha sonraki Android sürümlerinde yapabilirim (4.4 üzerinde test yapıyorum, bu yüzden sonraki sürümlerde daha iyi çalışıp çalışmadığından emin değilim). Şimdilik, bir zaman aşımı ayarlanmış gibi görünüyor:

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

Hayır öyle değil. Sunucu, isteği okuyana kadar yanıt göndermez. Aksine herhangi bir beklenti yanlıştır. HttpURLConnection' ile ilgisi yok. – EJP

+0

Sunucu, tüm gövdenin gönderilmesinden önce bir yanıt gönderiyor - yani, isteklerin üstbilgisini okuyor, isteğin tüm gövdesi gönderilmeden önce, gövdenin çok büyük olacağını ve yanıtı göndereceğini belirliyor. Bkz. [Bu cevap] (http://stackoverflow.com/a/13424453/1054890) –

+0

@EJP Bu bağlantıya bir göz attınız mı? Cevabımın doğru olduğunu görebildiğim kadarıyla değil, eğer daha iyi bir açıklama almak için iyi olur. –