2009-07-13 16 views
13

(Risolto - vedi commento)HttpURLConnection falliscono su Android

Ho una classe che implementa un caricamento di file in più parti. Il codice funziona su tutti i client Java che ho provato su Android, ed è l'unico codice di richiesta HTTP nella mia app per Android che non funziona correttamente con il mio servizio di back-end.

Il codice di risposta della connessione è "-1", quindi qualcosa di molto brutto sta succedendo qui. Nessuna voce appare nell'accesso Apache o nei log degli errori, sembra come se la richiesta non fosse mai riuscita ad uscire dalla piattaforma Android. Il codice passa direttamente attraverso le scritture di connessione, ma si blocca sulla connessione letta, scade e poi ritorna. Il comportamento è lo stesso per il telefono reale e l'emulatore.

Qualcuno sa di trucchi da tenere d'occhio quando si pubblica un file multipart in Android?

sto compresa la classe di seguito (mod igieniche minori fatta) in modo da poter vedere quello che sto fino a

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

Dopo molte ore di debugging, che risulta essere un bug nel nostro router che per qualche motivo o un altro è appeso su un viaggio di andata in uscita di nuovo nella nostra messa in scena server quando il messaggio supera i pochi k byte. Stavo sviluppando su un telefono che utilizzava la connessione di rete wireless e, naturalmente, l'emulatore utilizza anche la rete. Una volta preso di mira il nostro server di produzione, ha funzionato subito. Anche il cellulare è buono. – jottos

+3

Tutti si sentono liberi di utilizzare questa classe Android multipart/form-data. Funziona come un campione. Ed è facilmente generalizzabile a una classe generica multipart/form-data. suggerimento di pulizia sul codice: è possibile rimuovere i metodi getResponse() in favore di il metodo HttpURLConnection conn.getResponseMethod() e, naturalmente, conn.getResponseCode() per ottenere il codice del server http appropriato – jottos

risposta

2

Avete impostare l'autorizzazione ad internet? Mi assicuro che sia semplice ottenere (utilizzare HTTPUrl per recuperare google) prima di provare a eseguire il debug di post.

+0

sì, l'applicazione ottiene molto pochi Http - tutto successo – jottos

0

HI ho eseguito il caricamento di file utilizzando lo stesso HttpURLConnection. sono in grado di caricare file fino a 25 mb in servizi restful. uno sguardo questo potrebbe essere utile per voi: link

Problemi correlati