2012-09-03 9 views
8

この問題をデバッグしようと最後の日かかりましたが、私はアイデアがありません。基本的に私はいくつかのデータをPHP/Apache WebサーバーにポストしているAndroidアプリを持っています。このコードは、私のローカルテストサーバーを指すときにうまく動作するようです。私のプロダクションサーバを指すときにはうまくいくようですが、私が​​という行をコメントアウトするときだけです。その行が有効になると、その投稿はローカルのテストサーバー上でのみ動作しますが、運用サーバーにポストするときはPHP $ _FILES配列は空です。私はsetChunkedStreamingMode(0と1024を含む)に多数の値を渡そうとしましたが、どれも問題を解決していないようです。Java/Android HttpURLConnection setChunkedStreamingModeがすべてのPHPサーバで動作していません

現時点では、プロダクションサーバの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が空であるが、テストインスタンスでは空でないことを確認するスクリプトの最初の部分です。どんなアイデアでも大歓迎です。

+0

プロダクション構成の何かがこのモードが動作しないようにします – njzk2

+0

何があってもよいでしょうか? – BlueScreenOfTOM

+0

あなたはこの問題を解決しましたか? –

答えて

2

残念ながら、私はこの問題の直接的な解決策を見つけることができませんでしたが、回避策を見つけることができました。 conn.setChunkedStreamingModeを使用する代わりに、私はconn.setFixedLengthStreamingModeを使用しました。これは前に試してみましたが、成功しませんでした。 conn.setFixedLengthStreamingModeを稼働させる鍵は、送信しようとしているデータの全長(この場合はファイル)にヘッダーの長さを加えたものです。幸運にも、ヘッダーの長さは通常このようなコードで固定されています。ヘッダーの大きさを把握したら(Content-Dispositionのヘッダーで送信されるファイル名などのことを覚えておいてください)固定数で入力します。ヘッダーの長さを調べるために、ヘッダーの長さを指定せずに最初にコードを実行しました。私が受け取ったエラーメッセージは、送信されたバイト数の期待値と実際の値を与えてくれました。ヘッダー長を計算することができました。

+3

あなたはconnからヘッダーを見つけるのに使ったコードを置くことができますか? – desgraci

+0

@BlueScreenOfTOM:** conn.setFixedLengthStreamingMode **を使用すると、大きなビデオファイルでソケットタイムアウトエラーが発生します。そして私はあなたのコードを見て、それはタイムアウトのために200秒と言います。どのような基準で200秒を設定しましたか?しかし、** conn.setFixedLengthStreamingMode **を使用することによって、メモリエラーとソケットタイムアウトエラーの両方を取り除くことができます。 –

+0

これを行うと、全体のファイルをチャンクとしてアップロードすることになります。通常はこのメソッドの目的を無効にします – Vihar

関連する問題