Java/Android HttpURLConnection setChunkedStreamingMode funktioniert nicht mit allen PHP-Servern
Ich habe in den letzten Tag oder so versuchen zu Debuggen dieses Thema und ich bin aus Ideen heraus. Im Grunde habe ich eine Android-app, die Sie veröffentlicht einige Daten an ein PHP - /Apache-web-server. Dieser code scheint zu funktionieren, wenn ich es auf meinem lokalen server testen. Es scheint auch zu funktionieren, wenn ich es auf meinem Produktionsserver, aber NUR, wenn ich die folgende Zeile auskommentiert conn.setChunkedStreamingMode(maxBufferSize);
. Sobald diese Zeile aktiviert ist, wird die post funktioniert nur auf meinem lokalen test-server, aber beim posten auf den Produktions-server, PHP $_FILES array ist leer. Ich habe versucht, vorbei an zahlreichen Werte setChunkedStreamingMode
(einschließlich 0 und 1024) aber keiner von Ihnen scheinen, um das problem zu beheben.
In diesem Punkt gehe ich davon aus, das Problem hat zu tun mit der Art und Weise der Produktion der server PHP konfiguriert ist, aber soweit ich das beurteilen kann, alle wichtigen Parameter auf dem server sind die gleichen wie auf meiner test-Instanz. Zusätzlich, Sie sind beide die gleiche version von Apache und PHP. Mein Produktions-server wird von Bluehost.
Hier ist der Java code, den ich verwende zum hochladen:
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 verwende am anderen Ende zu erhalten:
$target = "userfiles/";
$target = $target . basename( $_FILES['uploadedfile']['name']);
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target))
{
echo "SUCCESS";
}
else
{
echo "FAIL";
}
Klebte ich mir print_r($_FILES);
ganz am Anfang des Skripts zu bestimmen, dass $_FILES leer ist auf die Produktion Instanz, aber nicht auf die test-Instanz. Irgendwelche Ideen würde sehr geschätzt werden.
- etwas in Ihrer Produktion Konfiguration verhindert, dass dieser Modus von der Arbeit
- Irgendwelche Vorschläge was das sein könnte?
- Haben Sie dieses Problem gelöst..?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Leider war ich nicht in der Lage zu finden, eine direkte Lösung zu diesem problem, jedoch konnte ich einen workaround finden. Anstelle der Verwendung von
conn.setChunkedStreamingMode
ich verwendetconn.setFixedLengthStreamingMode
, das hatte ich vorher versucht, ohne Erfolg. Der Schlüssel zuconn.setFixedLengthStreamingMode
zu arbeiten ist, um es zu übergeben und die volle Länge der Daten, die Sie versuchen zu senden (in diesem Fall die Datei), plus die Länge des headers. Zum Glück header-Länge ist in der Regel fest in code wie diesem, so dass, sobald Sie herausfinden, wie groß dein header ist (unter Berücksichtigung Dinge wie der Dateiname, die gesendet wird, in der Kopfzeile unter "Content-Disposition" ist ebenfalls variabel) können Sie einfach steckte es in eine Feste Anzahl. Um herauszufinden, meine header-Länge, lief ich den code zuerst ohne Angabe der Länge für den Kopf. Die Fehlermeldung erhielt ich zurück, gab mir einen erwarteten und einen tatsächlichen Wert für die Anzahl der gesendeten bytes an, die es mir erlaubt, die Berechnung der header-Länge.