2017-08-31 1 views
0

Ich muss eine komprimierte Datenbank (Nutzlast ~ 10 MB) an einen PHP-Webdienst senden, der SSL verwendet.Datei über HTTPS POST an Remote senden

Der Code funktionierte für Wochen, aber plötzlich bekomme ich eine ssl broken pipe exception (SSL Broken Pipe). Ich sehe keinen Grund für den Fehler - ich habe den Code nicht geändert und die Server-Konfiguration ist immer noch die gleiche (der IIS war in der Lage, die Datenübertragung von ssl vorher zu handhaben).

Derzeit verwende ich die java.net.HttpsURLConnection (Code unten) - welche Alternative würden Sie mir empfehlen, wenn Sie eine Datei von Android an einen Webdienst senden? Es scheint, dass der POST nicht auf dem Gerät verarbeitet wird.

Vielen Dank im Voraus

try { 
    final File compressedDb = new File(Environment.getExternalStorageDirectory() + "/" + Const.TMP_DIR + "/database.zip"); 
    String sourceFileUri = compressedDb.getPath(); 

final long compressedDbSize = compressedDb.length(); 
float optimized = ((float) _dbSize/(float) compressedDbSize) * 100f; 
int dbKb = (int) (((float) _dbSize)/1024f); 
int dbCompKb = (int) ((float) compressedDbSize/1024f); 
compressionInfo = getString(R.string.compression) + ": " + 
     dbKb + "kB " + getString(R.string.to) + " " + dbCompKb + "kB" + "<br>" + 
     getString(R.string.saved) + ": " + (int) optimized + "%" + "<br>"; 

Log.i(TAG, "DB name=" + compressedDb.getName() + " size=" + compressedDb.length()/1024 + "kB."); 

HttpsURLConnection connection; 
DataOutputStream dos; 
String lineEnd = "\r\n"; 
String twoHyphens = "--"; 
String boundary = "*****"; 
int bytesRead, bytesAvailable, bufferSize; 
byte[] buffer; 
File sourceFile = new File(sourceFileUri); 
//    int maxBufferSize = 1024 * 1024; 
int maxBufferSize = (int) sourceFile.length(); 

if (sourceFile.isFile()) { 

    try { 

     // open a URL connection to the Servlet 
     FileInputStream fileInputStream = new FileInputStream(sourceFile); 
     url = new URL(params[0]); 

connection = (HttpsURLConnection) url.openConnection(); 
connection.setDoInput(true); // Allow Inputs 
connection.setUseCaches(false); // Don't use a Cached Copy 
connection.setRequestMethod("POST"); 
connection.setRequestProperty("Connection", "Keep-Alive"); 
connection.setRequestProperty("ENCTYPE", "multipart/form-data"); 
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); 
connection.setRequestProperty("the_database", sourceFileUri); 

     dos = new DataOutputStream(connection.getOutputStream()); 

     dos.writeBytes(twoHyphens + boundary + lineEnd); 
     dos.writeBytes("Content-Disposition: form-data; name=\"the_database\";" + 
       "filename=\"" + sourceFileUri + "\"" + lineEnd); 

     dos.writeBytes(lineEnd); 

     // create a buffer of maximum size 
     bytesAvailable = fileInputStream.available(); 

     bufferSize = Math.min(bytesAvailable, maxBufferSize); 
     buffer = new byte[bufferSize]; 

     // read file and write it into form... 
     bytesRead = fileInputStream.read(buffer, 0, bufferSize); 

     int bytesTotal = bytesAvailable; 

     Log.i(TAG, "maxBuffer=" + maxBufferSize + 
       " | bytesTotal=" + bytesTotal + " | bytesAvailable=" + bytesAvailable); 

     while (bytesRead > 0) { 
      dos.write(buffer, 0, bufferSize); 
      bytesAvailable = fileInputStream.available(); 
      bufferSize = Math.min(bytesAvailable, maxBufferSize); 
      bytesRead = fileInputStream.read(buffer, 0, bufferSize); 
      int progress = 100 - (int) (((float) bytesAvailable * 100/(float) bytesTotal)); 
      publishProgress("" + progress); 
     } 

     // send multipart form data necessary after file data... 
     dos.writeBytes(lineEnd); 
     dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); 

     // Responses from the server (code and message) 
     int serverResponseCode = connection.getResponseCode(); 
     final String responseMessagePostDb = connection.getResponseMessage(); 

     fileInputStream.close(); 
     dos.flush(); 
     dos.close(); 

     if (responseMessagePostDb != null) { 
      responseStrings.add("<br>"); 
      responseStrings.add("<b><u>" + getString(R.string.optimisation_string) + "</u></b>" + "<br>"); 
      responseStrings.add(params[1]); 

      responseStrings.add("<b><u>" + getString(R.string.optimisation_database) + "</u></b>" + "<br>"); 
      responseStrings.add(compressionInfo); 

      String response = (responseMessagePostDb.equals("OK") ? ("<font color=\"" + GREEN + "\">PASSED</font>") : "FAILED"); 

      responseStrings.add(getString(R.string.server_response) + ": " + response); 
      return responseStrings; 
      } 

     } catch (Exception e) { 
      Log.e(TAG, "doInBackground: " + e.getMessage()); 
      responseStrings.add("FAILED2"); // <- this exception is thrown 
      responseStrings.add(e.getMessage()); 
      return responseStrings; 
     } 
    } 
} catch (Exception ex) { 
    Log.e(TAG, "doInBackground: " + ex.getMessage()); 
    responseStrings.add("FAILED3"); 
    responseStrings.add(ex.getMessage()); 
    return responseStrings; 
} 

Log.e(TAG, "doInBackground: " + "FAILED4"); 
responseStrings.add("FAILED4"); 
responseStrings.add("Unexpected Error..."); 
return responseStrings; 
+1

Auf die Frage "welche Alternative würden Sie empfehlen", ist meine Bibliothek der Wahl (wie für viele Entwickler) [Retrofit] (https://github.com/square/retrofit). –

Antwort

1

Wenn gearbeitet Code bis zu diesem Punkt, dann logisch, wenn Sie eine Race-Bedingung in Ihrem Code haben, sind Sie nicht inkonsistente Ergebnisse, wenn es isn‘gehen, um zu sehen t der Code. Mit anderen Worten, wenn der Server entschieden hat, ein Verbindungstimeout zu erzwingen, würde Ihr Code anscheinend ohne Grund scheitern. Sogar die Verknüpfung mit dem Problem, das eine SSL-Unterbrechungsrohren-Ausnahme beinhaltet, scheint zu implizieren, dass der Grund der Server und nicht der Client ist.

Mein Rat wäre, zu versuchen, verschiedene Gründe für den Fehler zu finden, die den Server einbeziehen, was er nicht tun sollte, und dann jede Theorie zu testen, indem Sie Ihren Code ändern. Mit anderen Worten, wenn das Problem eine Frage des Zeitlimits war, zeit die Operation und eine kleinere Datei über das Netzwerk senden und überprüfen, ob das funktioniert. Wenn dies der Fall ist, haben Sie Ihr Problem. Wenn nicht, dann gehe zur nächsten Theorie.

Leider kein Problem mit dem genannten Code, der dieses Problem unlösbar macht, ohne weitere Details zu kennen.

Verwandte Themen