2009-07-13 8 views
13

(Résolu - voir commentaire ci-dessous)HttpURLConnection échouent sur Android

J'ai une classe qui implémente un téléchargement de fichier multipart. Le code fonctionne sur tous les clients java sur lesquels j'ai essayé, sauf pour Android, et c'est le seul code de requête HTTP de mon application Android qui ne fonctionne pas bien avec mon service back-end.

La connexion responseCode est "-1" donc quelque chose de vraiment méchant se passe ici. Aucune entrée n'apparaît dans les journaux d'accès ou d'erreurs d'Apache, il semble que la requête ne se déconnecte jamais de la plate-forme Android. Le code passe à travers les écritures de connexion, mais se bloque sur la connexion lire, expire, puis revient. Le comportement est le même pour le vrai téléphone et l'émulateur.

Est-ce que quelqu'un connaît des pièges que l'on doit rechercher lors de la publication d'un fichier multipart dans Android?

Je y compris la classe ci-dessous (mods d'hygiène mineurs fait) afin que vous puissiez voir ce que je suis jusqu'à

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

Après de nombreuses heures de débogage, il se révèle être un bug dans notre routeur pour une raison ou une autre est suspendu sur un aller-retour en partance de retour dans notre mise en scène serveur lorsque le message est sur quelques k octets. J'avais développé sur un combiné qui utilisait la connexion réseau sans fil et bien sûr l'émulateur utilise également le réseau. Une fois que nous avons ciblé notre serveur de production, cela a fonctionné immédiatement. Cellulaire est bon aussi. – jottos

+3

Tout le monde s'il vous plaît n'hésitez pas à utiliser cette Android multipart/classes de données de formulaire. Cela fonctionne comme un champion. Et est facilement généralisé à une classe multipart/form-data générique. Astuce de nettoyage sur le code - vous pouvez supprimer les méthodes getResponse() en faveur de la méthode HttpURLConnection conn.getResponseMethod(), et bien sûr le conn.getResponseCode() pour obtenir le bon code serveur http – jottos

Répondre

2

Avez-vous défini l'autorisation d'Internet? Je ferais en sorte que Gets simples (Utilisez le HTTPUrl pour aller chercher google) avant d'essayer de déboguer un message.

+0

oui, l'application fait un peu de Http obtient - tous avec succès – jottos

0

HI j'ai fait le téléchargement de fichier en utilisant même HttpURLConnection. Je peux télécharger des fichiers jusqu'à 25 Mo dans des services reposants. un coup d'oeil cela pourrait être utile pour vous: link

Questions connexes