2012-09-03 11 views
8

Ho passato l'ultimo giorno o giù di lì cercando di eseguire il debug di questo problema e sono fuori dalle idee. Fondamentalmente ho un'app per Android che invia POST di alcuni dati ad un server web PHP/Apache. Questo codice sembra funzionare correttamente quando lo indico sul mio server di test locale. Sembra funzionare bene anche quando lo indico sul mio server di produzione, ma SOLO quando commento la linea conn.setChunkedStreamingMode(maxBufferSize);. Una volta abilitata questa riga, il post funziona solo sul mio server di test locale, ma quando si postano sul server di produzione, l'array $ _FILES PHP è vuoto. Ho provato a passare numerosi valori a setChunkedStreamingMode (inclusi 0 e 1024) ma nessuno di questi sembra risolvere il problema.Java/Android HttpURLConnection setChunkedStreamingMode non funziona con tutti i server PHP

A questo punto presumo che il problema riguardi il modo in cui è configurato il PHP del server di produzione, ma per quanto posso dire, tutti i parametri importanti sul server sono gli stessi della mia istanza di test. Inoltre, entrambi eseguono la stessa versione di Apache e PHP. Il mio server di produzione è gestito da Bluehost.

Ecco il codice Java che sto usando per caricare:

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

Ed ecco il codice PHP che sto utilizzando sull'altra estremità per ricevere:

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

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

ho attaccato un print_r($_FILES); a proprio all'inizio dello script per determinare che $ _FILES è vuoto sull'istanza di produzione, ma non sull'istanza di test. Qualsiasi idea sarebbe molto apprezzata.

+0

qualcosa nella configurazione di produzione impedisce il funzionamento di questa modalità – njzk2

+0

Qualche suggerimento su cosa potrebbe essere? – BlueScreenOfTOM

+0

Hai risolto questo problema ..? –

risposta

2

Purtroppo non sono riuscito a trovare una soluzione diretta a questo problema, ma sono riuscito a trovare una soluzione alternativa. Invece di usare conn.setChunkedStreamingMode ho usato conn.setFixedLengthStreamingMode, che avevo provato prima senza successo. La chiave per far funzionare conn.setFixedLengthStreamingMode consiste nel passargli tutta la lunghezza dei dati che stai tentando di inviare (in questo caso il file), più la lunghezza delle intestazioni. Fortunatamente la lunghezza dell'intestazione è solitamente fissata in codice come questo, quindi una volta capito quanto è grande l'intestazione (tenendo presente che cose come il nome del file, che viene inviato nell'intestazione sotto Content-Disposition è anche variabile) puoi semplicemente metterlo in come un numero fisso. Per capire la mia lunghezza dell'intestazione, ho eseguito il codice prima senza specificare alcuna lunghezza per l'intestazione. Il messaggio di errore che ho ricevuto mi ha dato un valore atteso e reale per il numero di byte inviati, il che mi ha permesso di calcolare la lunghezza dell'intestazione.

+3

puoi inserire il codice che hai usato per scoprire le intestazioni dal conn? – desgraci

+0

@BlueScreenOfTOM: utilizzando ** conn.setFixedLengthStreamingMode ** sto ottenendo errore sockettimeout per file video di grandi dimensioni. E ho visto il tuo codice e dice 200 secondi per il timeout. quindi su quali basi hai impostato 200 sec? Ma usando ** conn.setFixedLengthStreamingMode ** sono in grado di eliminare anche l'errore di memoria esaurita e l'errore di timeout del socket. –

+0

in questo modo, stai dicendo che tutto il file verrà caricato come un chunk, che in genere sconfigge lo scopo di questo metodo – Vihar

Problemi correlati