Java / Android HttpURLConnection setChunkedStreamingMode не работает со всеми серверами PHP

Я провел последний день или около того, пытаясь отладить эту проблему, и у меня нет идей. В основном у меня есть приложение для Android, которое отправляет некоторые данные на веб-сервер PHP / Apache. Этот код работает нормально, когда я указываю его на локальном тестовом сервере. Он также отлично работает, когда я указываю его на моем рабочем сервере, но ТОЛЬКО, когда я прокомментирую строку conn.setChunkedStreamingMode(maxBufferSize); , После того, как эта строка включена, пост работает только на моем локальном тестовом сервере, но при отправке на производственный сервер массив PHP $ _FILES пуст. Я попытался передать множество значений setChunkedStreamingMode (включая 0 и 1024), но ни один из них, похоже, не setChunkedStreamingMode проблему.

На этом этапе я предполагаю, что проблема связана с тем, как настроен PHP-сервер производственного сервера, но насколько я могу судить, все важные параметры на сервере такие же, как и в моем тестовом экземпляре. Кроме того, они оба запускают ту же версию Apache и PHP. Мой сервер работает под управлением Bluehost.

Вот код Java, который я использую для загрузки:

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

И вот код PHP, который я использую на другом конце, чтобы получить:

 $target = "userfiles/"; $target = $target . basename( $_FILES['uploadedfile']['name']); if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target)) { echo "SUCCESS"; } else { echo "FAIL"; } 

Я застрял print_r($_FILES); В самом начале скрипта, чтобы определить, что $ _FILES пуст в производственном экземпляре, но не в тестовом экземпляре. Любые идеи очень приветствуются.

К сожалению, я не смог найти прямое решение этой проблемы, но мне удалось найти обходное решение. Вместо использования conn.setChunkedStreamingMode я использовал conn.setFixedLengthStreamingMode , который я пробовал до этого без успеха. Ключ к тому, чтобы заставить conn.setFixedLengthStreamingMode работать, – это передать ему всю длину данных, которые вы пытаетесь отправить (в этом случае файл), плюс длина заголовков. К счастью, длина заголовка обычно фиксируется в коде, например, так, как только вы выясните, насколько велик ваш заголовок (имея в виду такие вещи, как имя файла, которое отправляется в заголовке в Content-Disposition, также является переменной), вы можете просто поместить его В качестве фиксированного числа. Чтобы выяснить длину моего заголовка, я сначала запустил код без указания длины для заголовка. Сообщение об ошибке, которое я получил, дал мне ожидаемое и фактическое значение для количества отправленных байтов, что позволило мне вычислить длину заголовка.