Java/Android HttpURLConnection setChunkedStreamingMode不适用于所有PHP服务器

Java/Android HttpURLConnection setChunkedStreamingMode不适用于所有PHP服务器,java,php,android,Java,Php,Android,我花了大约最后一天的时间来调试这个问题,我已经没有主意了。基本上,我有一个Android应用程序,它将一些数据发布到PHP/Apache web服务器。当我将此代码指向本地测试服务器时,它似乎工作正常。当我将它指向我的生产服务器时,它似乎也能正常工作,但只有当我注释掉conn.setChunkedStreamingMode(maxBufferSize)行时,它才能正常工作。启用该行后,post仅在本地测试服务器上工作,但在发布到生产服务器时,PHP$\u文件数组为空。我曾尝试将许多值传递给set

我花了大约最后一天的时间来调试这个问题,我已经没有主意了。基本上,我有一个Android应用程序,它将一些数据发布到PHP/Apache web服务器。当我将此代码指向本地测试服务器时,它似乎工作正常。当我将它指向我的生产服务器时,它似乎也能正常工作,但只有当我注释掉conn.setChunkedStreamingMode(maxBufferSize)行时,它才能正常工作。启用该行后,post仅在本地测试服务器上工作,但在发布到生产服务器时,PHP$\u文件数组为空。我曾尝试将许多值传递给
setChunkedStreamingMode
(包括0和1024),但这些似乎都无法解决问题

此时,我假设问题与生产服务器的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($\u文件)
在脚本的最开始处,确定生产实例上的$\u文件为空,而测试实例上的$\u文件为空。任何想法都将不胜感激。

不幸的是,我无法找到这个问题的直接解决方案,但我找到了解决办法。我没有使用
conn.setChunkedStreamingMode
,而是使用了
conn.setFixedLengthStreamingMode
,我以前尝试过,但没有成功。使
conn.setFixedLengthStreamingMode
正常工作的关键是将您试图发送的数据的完整长度(在本例中为文件)加上标题的长度传递给它。幸运的是,在这样的代码中,头的长度通常是固定的,因此,一旦您确定了头的大小(请记住文件名之类的内容,它在“内容处置”下发送到头中也是可变的),您就可以将其作为固定的数字输入。为了计算头的长度,我首先运行了代码,没有为头指定任何长度。我收到的错误消息为我提供了发送的字节数的预期值和实际值,这使我能够计算标题长度。

生产配置中的某些内容阻止此模式运行任何关于这可能是什么的建议?您解决了此问题吗?@BlueScreenOfTOM:使用conn.setFixedLengthStreamingMode,我得到了sockettimeout大型视频文件出错。我看到了你的代码,上面写着200秒超时。那么你是根据什么设定的200秒?但是通过使用conn.setFixedLengthStreamingMode,我还能够消除内存不足错误和套接字超时错误。这样做,您告诉整个文件将作为一个块上载,这通常不符合此方法的目的