2012-09-03 8 views
8

Spędziłem ostatni dzień, próbując debugować ten problem i nie mam pomysłów. Zasadniczo mam aplikację na Androida, która wysyła pewne dane do serwera WWW PHP/Apache. Ten kod wydaje się działać dobrze, gdy wskażę go na moim lokalnym serwerze testowym. Wydaje się również działać dobrze, gdy wskażę go na moim serwerze produkcyjnym, ale TYLKO wtedy, gdy skomentuję linię conn.setChunkedStreamingMode(maxBufferSize);. Po włączeniu tej linii post działa tylko na moim lokalnym serwerze testowym, ale podczas wysyłania wiadomości na serwer produkcyjny tablica PHP $ _FILES jest pusta. Próbowałem przekazać wiele wartości do setChunkedStreamingMode (w tym 0 i 1024), ale żaden z nich nie wydaje się naprawić problem.Java/Android HttpURLConnection setChunkedStreamingMode nie działa ze wszystkimi serwerami PHP

W tym momencie zakładam, że problem dotyczy sposobu, w jaki skonfigurowano PHP serwera produkcyjnego, ale o ile wiem, wszystkie ważne parametry na serwerze są takie same, jak w mojej instancji testowej. Dodatkowo oba działają z tą samą wersją Apache i PHP. Mój serwer produkcyjny jest zarządzany przez Bluehost.

Oto kod Java używam przesłać:

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

A oto kod PHP używam na drugim końcu otrzymywać:

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

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

Wsadziłem do print_r($_FILES); w na samym początku skryptu, aby stwierdzić, że $ _FILES jest puste w instancji produkcyjnej, ale nie w instancji testowej. Wszelkie pomysły będą mile widziane.

+0

coś w konfiguracji produkcyjnej uniemożliwia działanie tego trybu. – njzk2

+0

Jakieś sugestie co to może być? – BlueScreenOfTOM

+0

Rozwiązałeś ten problem ..? –

Odpowiedz

2

Niestety nie udało mi się znaleźć bezpośredniego rozwiązania tego problemu, ale udało mi się znaleźć obejście problemu. Zamiast używać conn.setChunkedStreamingMode użyłem conn.setFixedLengthStreamingMode, którego próbowałem wcześniej bez powodzenia. Kluczem do uzyskania pracy conn.setFixedLengthStreamingMode jest przekazanie jej pełnej długości danych, które próbujesz wysłać (w tym przypadku pliku), oraz długość nagłówków. Na szczęście długość nagłówka jest zwykle ustalana w kodzie takim jak ten, więc gdy już się zorientujesz, jak duży jest twój nagłówek (pamiętając o takich elementach jak nazwa pliku, który jest wysyłany w nagłówku w sekcji Content-Disposition jest również zmienny), możesz po prostu go umieścić w postaci stałej liczby. Aby obliczyć długość mojego nagłówka, najpierw uruchomiłem kod bez określania długości nagłówka. Otrzymany przeze mnie komunikat o błędzie dał mi oczekiwaną i aktualną wartość liczby wysłanych bajtów, co pozwoliło mi obliczyć długość nagłówka.

+3

możesz umieścić kod, którego użyłeś, aby znaleźć nagłówki z połączenia? – desgraci

+0

@ BlueScreenOfTOM: Za pomocą ** conn.setFixedLengthStreamingMode ** otrzymuję błąd sockettimeout dla dużych plików wideo. I widziałem twój kod i mówi 200 sekund na time out. więc na jakiej podstawie ustawiłeś 200 sekund? Ale przy użyciu ** conn.setFixedLengthStreamingMode ** jestem w stanie wyeliminować zarówno błąd braku pamięci, jak i błąd przekroczenia limitu czasu gniazda. –

+0

robiąc to, mówisz całemu plikowi, że chcesz go załadować jako porcję, co zwykle psuje cel tej metody – Vihar

Powiązane problemy