2012-09-03 17 views
8

Ich habe den letzten Tag oder so versucht, dieses Problem zu debuggen und ich habe keine Ideen mehr. Grundsätzlich habe ich eine Android-App, die einige Daten an einen PHP/Apache-Webserver sendet. Dieser Code scheint gut zu funktionieren, wenn ich ihn auf meinen lokalen Testserver zeige. Es scheint auch gut zu funktionieren, wenn ich es auf meinen Produktionsserver zeige, aber NUR, wenn ich die Zeile conn.setChunkedStreamingMode(maxBufferSize); auszeichne. Sobald diese Zeile aktiviert ist, funktioniert der Post nur auf meinem lokalen Testserver, aber wenn auf den Produktionsserver geschrieben wird, ist das PHP $ _FILES-Array leer. Ich habe versucht, zahlreiche Werte an setChunkedStreamingMode (einschließlich 0 und 1024) zu übergeben, aber keine von ihnen scheint das Problem zu beheben.Java/Android HttpURLConnection setChunkedStreamingMode funktioniert nicht mit allen PHP-Servern

An dieser Stelle nehme ich an, dass das Problem mit der Art und Weise zu tun hat, wie der PHP des Produktionsservers konfiguriert ist, aber soweit ich weiß, sind alle wichtigen Parameter auf dem Server die gleichen wie auf meiner Testinstanz. Darüber hinaus verwenden beide dieselbe Version von Apache und PHP. Mein Produktionsserver wird von Bluehost betrieben.

Hier ist der Java-Code, den ich laden bin mit:

HttpURLConnection conn = null; 
DataOutputStream dos = null; 
DataInputStream inStream = null; 
String lineEnd = "\r\n"; 
String twoHyphens = "--"; 
String boundary = "***************************************************"; 
int bytesRead, bytesAvailable, bufferSize; 
byte[] buffer; 
int maxBufferSize = 212144; // 1024*1024 = 1MB. 212144 is a quarter MB. 
FileInputStream fileInputStream = null; 
try 
{ 
    // ------------------ CLIENT REQUEST 
    fileInputStream = new FileInputStream(new File(existingFileWithFullPath)); 
    // open a URL connection to the Servlet 
    URL url = new URL(BACKUP_POST_URL); 
    // Open a HTTP connection to the URL 
    conn = (HttpURLConnection) url.openConnection(); 
    // Allow Inputs 
    conn.setDoInput(true); 
    // Allow Outputs 
    conn.setDoOutput(true); 
    // Send in chunks (to avoid out of memory error) 
    conn.setChunkedStreamingMode(maxBufferSize); 
    // Don't use a cached copy. 
    conn.setUseCaches(false); 
    // Use a post method. 
    conn.setRequestMethod("POST"); 
    conn.setRequestProperty("Connection", "Keep-Alive"); 
    conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" 
     + boundary); 
    conn.setReadTimeout(200000); // 200 seconds... 
    dos = new DataOutputStream(conn.getOutputStream()); 
    dos.writeBytes(twoHyphens + boundary + lineEnd); 
    dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" 
     + fileName + "\"" + 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); 
    while (bytesRead > 0) 
    { 
    try { 
     dos.write(buffer, 0, bufferSize);   
    } catch (OutOfMemoryError oome) { 
     Log.e(CommonStatic.LOG_NAME, "Out of memory error caught..."); 
     oome.printStackTrace(); 
     fileInputStream.close(); 
     throw new Exception("Out Of Memory!"); 
    } 
    bytesAvailable = fileInputStream.available(); 
    bufferSize = Math.min(bytesAvailable, maxBufferSize); 
    bytesRead = fileInputStream.read(buffer, 0, bufferSize); 
    } 
    // send multipart form data necesssary after file data... 
    dos.writeBytes(lineEnd); 
    dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); 
    fileInputStream.close(); 
    dos.flush(); 
    dos.close(); 

    // close streams 
    Log.d(CommonStatic.LOG_NAME, "Backup file written to server successfully..."); 
} 
catch (Exception ex) 
{ 
    Log.e(CommonStatic.LOG_NAME, "Backup File Upload Error: " + ex.getMessage(), ex); 
    throw new Exception (c.getString(R.string.SAVE_TO_CLOUD_ERROR)); 
} 

Und hier ist der PHP-Code, den ich am anderen Ende bin mit erhalten:

$target = "userfiles/"; 
$target = $target . basename($_FILES['uploadedfile']['name']); 

if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target)) 
{ 
    echo "SUCCESS"; 
} 
else 
{ 
    echo "FAIL"; 
} 

Ich steckte ein print_r($_FILES); an Ganz am Anfang des Skripts, um zu bestimmen, dass $ _FILES in der Produktionsinstanz leer ist, aber nicht in der Testinstanz. Irgendwelche Ideen würden sehr geschätzt werden.

+0

etwas in Ihrer Produktionskonfiguration verhindert, dass dieser Modus funktioniert – njzk2

+0

Irgendwelche Vorschläge, was das sein könnte? – BlueScreenOfTOM

+0

Haben Sie dieses Problem gelöst ..? –

Antwort

2

Leider konnte ich keine direkte Lösung für dieses Problem finden, aber ich konnte einen Workaround finden. Anstatt conn.setChunkedStreamingMode zu verwenden, benutzte ich conn.setFixedLengthStreamingMode, die ich vorher ohne Erfolg versucht hatte. Der Schlüssel zu conn.setFixedLengthStreamingMode zu arbeiten ist es, übergeben Sie die volle Länge der Daten, die Sie senden möchten (in diesem Fall die Datei), plus die Länge der Header. Glücklicherweise ist die Header-Länge normalerweise in Code wie diesem festgelegt. Wenn Sie also herausgefunden haben, wie groß Ihr Header ist (denken Sie daran, dass der Dateiname, der in der Kopfzeile unter Content-Disposition gesendet wird, ebenfalls variabel ist), können Sie ihn einfach setzen als feste Zahl. Um meine Header-Länge herauszufinden, habe ich den Code zuerst ohne Angabe einer Länge für den Header ausgeführt. Die Fehlermeldung, die ich zurück erhielt, gab mir einen erwarteten und einen tatsächlichen Wert für die Anzahl der gesendeten Bytes, was es mir ermöglichte, die Header-Länge zu berechnen.

+3

können Sie den Code, den Sie verwendet haben, um die Header aus dem Conn zu finden? – desgraci

+0

@BlueScreenOfTOM: Durch die Verwendung von ** conn.setFixedLengthStreamingMode ** bekomme ich den SocketTimeout-Fehler für große Videodateien. Und ich sah deinen Code und es sagt 200 Sekunden für die Auszeit. also auf welcher grundlage hast du 200 sek eingestellt? Aber mit ** conn.setFixedLengthStreamingMode ** bin ich in der Lage, sowohl den Fehler "out of memory error" als auch den Socket Timeout Fehler zu eliminieren. –

+0

indem Sie dies tun, sagen Sie ganze Datei yo hochgeladen werden als ein Brocken, die in der Regel den Zweck dieser Methode besiegt – Vihar

Verwandte Themen