2009-07-13 9 views
13

(rozwiązana - patrz komentarz poniżej)HttpURLConnection zawieść na Androida

Mam klasy, która implementuje wieloczęściowy upload plików. Kod działa na każdym kliencie Java, na którym go wypróbowałem, z wyjątkiem Androida, i jest to jedyny kod żądania HTTP w mojej aplikacji na Androida, który nie działa dobrze z moją usługą typu back-end.

Kod odpowiedzi połączenia to "-1", więc dzieje się tutaj coś bardzo nieprzyjemnego. W dziennikach dostępu i błędów Apache nie pojawiają się żadne wpisy, wydaje się, że żądanie nigdy nie jest wyłączone z platformy Android. Kod przechodzi przez zapisy połączenia, ale zawiesza się w odczytaniu połączenia, przekracza limit czasu, a następnie zwraca. Zachowanie jest takie samo dla prawdziwego telefonu i emulatora.

Czy ktoś wie o jakichś problemach, na które trzeba zwrócić uwagę, publikując plik wieloczęściowy w systemie Android?

jestem tym klasę poniżej (drobne higienicznych modów wykonany), dzięki czemu można zobaczyć, co mam do

import java.io.ByteArrayOutputStream; 
import java.io.DataOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.HttpURLConnection; 
import java.net.MalformedURLException; 
import java.net.URL; 

public class GeoPictureUploader 
{ 
    static String serviceDomain = "http://staging.abaqus.net"; 
    static String postUrl = serviceDomain + "/geo/upl/wupload/pictures"; 
    static String CRLF = "\r\n"; 
    static String twoHyphens = "--"; 
    static String boundary = "*****mgd*****"; 

    private String pictureFileName = null; 
    private String name = null; 
    private String password = null; 
    private DataOutputStream dataStream = null; 

    enum ReturnCode { noPicture, unknown, http201, http400, http401, http403, http404, http500}; 

    public GeoPictureUploader(String name, String password) 
    { 
     this.name = name; 
     this.password = password; 
    } 

    public static void setServiceDomain(String domainName) 
    { 
     serviceDomain = domainName; 
    } 

    public static String getServiceDomain() 
    { 
     return serviceDomain; 
    } 

    public ReturnCode uploadPicture(String pictureFileName) 
    { 
     this.pictureFileName = pictureFileName; 
     File uploadFile = new File(pictureFileName); 

     if (uploadFile.exists()) 
      try 
      { 
       FileInputStream fileInputStream = new FileInputStream(uploadFile); 
       URL connectURL = new URL(postUrl); 
       HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection(); 

       conn.setDoInput(true); 
       conn.setDoOutput(true); 
       conn.setUseCaches(false); 
       conn.setRequestMethod("POST"); 

       conn.setRequestProperty("User-Agent", "myGeodiary-V1"); 
       conn.setRequestProperty("Connection","Keep-Alive"); 
       conn.setRequestProperty("Content-Type","multipart/form-data;boundary="+boundary); 

       conn.connect(); 

       dataStream = new DataOutputStream(conn.getOutputStream()); 

       writeFormField("login", name); 
       writeFormField("password", password); 
       writeFileField("photo1", pictureFileName, "image/jpg", fileInputStream); 

       // final closing boundary line 
       dataStream.writeBytes(twoHyphens + boundary + twoHyphens + CRLF); 

       fileInputStream.close(); 
       dataStream.flush(); 
       dataStream.close(); 
       dataStream = null; 

       String response = getResponse(conn); 
       int responseCode = conn.getResponseCode(); 

       if (response.contains("uploaded successfully")) 
        return ReturnCode.http201; 
       else 
        // for now assume bad name/password 
        return ReturnCode.http401; 
      } 
      catch (MalformedURLException mue) { 
       // Log.e(Tag, "error: " + mue.getMessage(), mue); 
       System.out.println("GeoPictureUploader.uploadPicture: Malformed URL: " + mue.getMessage()); 
       return ReturnCode.http400; 
      } 
      catch (IOException ioe) { 
       // Log.e(Tag, "error: " + ioe.getMessage(), ioe); 
       System.out.println("GeoPictureUploader.uploadPicture: IOE: " + ioe.getMessage()); 
       return ReturnCode.http500; 
      } 
      catch (Exception e) { 
       // Log.e(Tag, "error: " + ioe.getMessage(), ioe); 
       System.out.println("GeoPictureUploader.uploadPicture: unknown: " + e.getMessage()); 
       return ReturnCode.unknown; 
      } 
     else 
     { 
      return ReturnCode.noPicture; 
     } 
    } 

    /** 
    * @param conn 
    * @return 
    */ 
    private String getResponse(HttpURLConnection conn) 
    { 
     try 
     { 
      DataInputStream dis = new DataInputStream(conn.getInputStream()); 
      byte []  data = new byte[1024]; 
      int    len = dis.read(data, 0, 1024); 

      dis.close(); 
      int responseCode = conn.getResponseCode(); 

      if (len > 0) 
       return new String(data, 0, len); 
      else 
       return ""; 
     } 
     catch(Exception e) 
     { 
      System.out.println("GeoPictureUploader: biffed it getting HTTPResponse"); 
      //Log.e(TAG, "GeoPictureUploader: biffed it getting HTTPResponse"); 
      return ""; 
     } 
    } 

    /** 
    * this mode of reading response no good either 
    */ 
    private String getResponseOrig(HttpURLConnection conn) 
    { 
     InputStream is = null; 
     try 
     { 
      is = conn.getInputStream(); 
      // scoop up the reply from the server 
      int ch; 
      StringBuffer sb = new StringBuffer(); 
      while((ch = is.read()) != -1) { 
       sb.append((char)ch); 
      } 
      return sb.toString(); // TODO Auto-generated method stub 
     } 
     catch(Exception e) 
     { 
      System.out.println("GeoPictureUploader: biffed it getting HTTPResponse"); 
      //Log.e(TAG, "GeoPictureUploader: biffed it getting HTTPResponse"); 
     } 
     finally 
     { 
      try { 
      if (is != null) 
       is.close(); 
      } catch (Exception e) {} 
     } 

     return ""; 
    } 

    /** 
    * write one form field to dataSream 
    * @param fieldName 
    * @param fieldValue 
    */ 
    private void writeFormField(String fieldName, String fieldValue) 
    { 
     try 
     { 
      dataStream.writeBytes(twoHyphens + boundary + CRLF);  
      dataStream.writeBytes("Content-Disposition: form-data; name=\"" + fieldName + "\"" + CRLF); 
      dataStream.writeBytes(CRLF); 
      dataStream.writeBytes(fieldValue); 
      dataStream.writeBytes(CRLF); 
     } 
     catch(Exception e) 
     { 
      System.out.println("GeoPictureUploader.writeFormField: got: " + e.getMessage()); 
      //Log.e(TAG, "GeoPictureUploader.writeFormField: got: " + e.getMessage()); 
     } 
    } 

    /** 
    * write one file field to dataSream 
    * @param fieldName - name of file field 
    * @param fieldValue - file name 
    * @param type - mime type 
    * @param fileInputStream - stream of bytes that get sent up 
    */ 
    private void writeFileField(
     String fieldName, 
     String fieldValue, 
     String type, 
     FileInputStream fis) 
    { 
     try 
     { 
      // opening boundary line 
      dataStream.writeBytes(twoHyphens + boundary + CRLF);  
      dataStream.writeBytes("Content-Disposition: form-data; name=\"" 
            + fieldName 
            + "\";filename=\"" 
            + fieldValue 
            + "\"" 
            + CRLF); 
      dataStream.writeBytes("Content-Type: " + type + CRLF); 
      dataStream.writeBytes(CRLF); 

      // create a buffer of maximum size 
      int bytesAvailable = fis.available(); 
      int maxBufferSize = 1024; 
      int bufferSize = Math.min(bytesAvailable, maxBufferSize); 
      byte[] buffer = new byte[bufferSize]; 
      // read file and write it into form... 
      int bytesRead = fis.read(buffer, 0, bufferSize); 
      while (bytesRead > 0) 
      { 
       dataStream.write(buffer, 0, bufferSize); 
       bytesAvailable = fis.available(); 
       bufferSize = Math.min(bytesAvailable, maxBufferSize); 
       bytesRead = fis.read(buffer, 0, bufferSize); 
      } 

      // closing CRLF 
      dataStream.writeBytes(CRLF); 
     } 
     catch(Exception e) 
     { 
      System.out.println("GeoPictureUploader.writeFormField: got: " + e.getMessage()); 
      //Log.e(TAG, "GeoPictureUploader.writeFormField: got: " + e.getMessage()); 
     } 
    } 


    /** 
    * @param args 
    */ 
    public static void main(String[] args) 
    { 
     if (args.length >= 0) 
     { 
      GeoPictureUploader gpu = new GeoPictureUploader("john", "notmyrealpassword"); 
      String picName = args[0]; 

      ReturnCode rc = gpu.uploadPicture(picName); 
      System.out.printf("done"); 
     } 
    } 

} 
+0

Po wielu godzinach debugowanie, okazuje się, że to błąd w naszym routerze że z jakiegoś powodu lub innego wisi na wyjazdowej obie z powrotem do naszej inscenizacji serwer, gdy wiadomość przekroczy kilka kilobajtów. Pracowałem nad telefonem, który korzystał z bezprzewodowego połączenia sieciowego i oczywiście Emulator również korzysta z sieci. Po skierowaniu naszego serwera produkcyjnego działało to od razu. Komórkowa też jest dobra. – jottos

+3

Wszystkich prosimy o korzystanie z tej wielowarstwowej/formularzy danych Android. Działa jak mistrz. I jest łatwo uogólniony do ogólnej klasy wieloczęściowej/formularza danych. Wskazówki dotyczące czyszczenia kodu - możesz usunąć metody getResponse() na rzecz metody HttpURLConnection conn.getResponseMethod() i oczywiście conn.getResponseCode(), aby uzyskać prawidłowy kod serwera http – jottos

Odpowiedz

2

Czy ustawić uprawnienie do internetu? Upewnię się, że prosty Gets (użyj HTTPUrl do pobrania google) przed próbą debugowania postu.

+0

tak, aplikacja robi sporo Http - wszystko udane – jottos

0

HI Wysyłałem pliki za pomocą tego samego HttpURLConnection. Jestem w stanie przesłać pliki do 25 MB na usługi spokojne. przyjrzeć to może być pomocne dla Ciebie: link

Powiązane problemy