2016-04-04 16 views
0

Ich versuche, eine Datei an unseren Server mit HttpURLConnection auf Android zu senden, aber der getResponseCode-Aufruf hängt nur und wird nie zurückgegeben. Das Problem rührt daher, dass die Datei zu groß für den Server ist. Daher sendet der Server einen HTTP-Fehlercode von 413 (den ich in den Serverprotokollen sehen kann), aber auf unserem Gerät scheint es, als ob dieser nie empfangen wird. Ich habe den folgenden Code in unserer App:HttpURLConnection getResponseCode nicht zurück

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

nur zu wiederholen, die Frage ist nicht ‚Warum ist der Server der Upload-Ablehnung‘, es ist, warum HttpURLConnection nicht den Antwortcode zu holen scheint. Wenn man in den Debugger einbricht, sieht es so aus, als ob HttpURLConnection beim Schreiben des Ausgabepuffers feststeckt, aber der Server hat bereits den Antwortcode gesendet, bevor die Anwendung den Ausgabepuffer beendet hat (da der Server den POST basierend auf dem Header abgelehnt hat). Der Server ist Nginx Weiterleitung an eine Node.JS-Instanz, wenn das überhaupt hilft, aber wie ich die 413 in den Protokollen sehe, denke ich, dass es ein Problem auf der Seite der App ist. Es hängt an der folgenden Zeile:

int status = httpURLConnection.getResponseCode(); 

Antwort

-1

So stellt sich heraus die Frage nach unten ist HttpURLConnection wollte den ganzen Körper laden, bevor eine der Antwort zu lesen. Nginx sendet die 413-Antwort und schließt die Verbindung, bevor die App den Body gesendet hat, aber HttpURLConnection versucht immer noch, den Body zu senden. Da die Verbindung am Nginx-Ende geschlossen ist, schlägt das Senden der Daten fehl, aber es gibt kein Standard-Zeitlimit, das von HttpURLConnection angegeben wird. Idealerweise würde HttpURLConnection beim Versuch, die Ausgabe zu schreiben, nach Early Response-Headern suchen, und dies könnte in späteren Android-Versionen geschehen (ich teste auf Version 4.4, also bin ich mir nicht sicher, ob dies in späteren Versionen besser funktioniert). Vorerst scheint ein Timeout zu funktionieren:

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

Nein, ist es nicht. Der Server sendet die Antwort erst, wenn er die Anforderung gelesen hat. Jede gegenteilige Erwartung ist fehl am Platz. Nichts mit 'HttpURLConnection' zu tun. – EJP

+0

Der Server sendet eine Antwort, bevor der gesamte Nachrichtentext gesendet wird - d. H. Er liest die Header aus der Anforderung, bestimmt, dass der Nachrichtentext zu groß ist, und sendet die Antwort, bevor der gesamte Nachrichtentext gesendet wurde. Siehe [diese Antwort] (http://stackoverflow.com/a/13424453/1054890) –

+0

@EJP Haben Sie sich diesen Link angesehen? Soweit ich sehen kann, ist meine Antwort richtig, aber es wäre gut, eine bessere Erklärung zu bekommen, wenn es nicht so ist. –

Verwandte Themen