2011-02-04 15 views
10

Tengo problemas para cargar imágenes en Android.Android archivo httpclient cargar problemas de corrupción y tiempo de espera

estoy usando Apache httpmime 4.1 lib el código es así:

MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); 

reqEntity.addPart("image", new FileBody(new File(AndorraApplication.getPhotosPath() + "/" + entity.getFileName()), "image/jpeg")); 
resp = NetworkUtils.sendHttpRequestMultipart(EXPORT_PHOTOS_URI, reqEntity); 

clase NetworkUtils:

public class NetworkUtils { 
    public static final int REGISTRATION_TIMEOUT = 3 * 1000; 
    public static final int WAIT_TIMEOUT = 5 * 1000; 

    public static HttpResponse sendHttpRequestMultipart(String uri, MultipartEntity entity) { 
     HttpClient mHttpClient = new DefaultHttpClient(); 
     final HttpParams params = mHttpClient.getParams(); 
     HttpConnectionParams.setConnectionTimeout(params, REGISTRATION_TIMEOUT); 
     HttpConnectionParams.setSoTimeout(params, WAIT_TIMEOUT); 
     ConnManagerParams.setTimeout(params, WAIT_TIMEOUT); 

     HttpPost post = new HttpPost(uri); 
     post.addHeader(entity.getContentType()); 
     post.setEntity(entity); 
     HttpResponse resp = mHttpClient.execute(post); 
    } 
} 

veces todo funciona bien, pero a veces (sobre todo en una conexión lenta) la imagen está cargada muy corrupta. el ejemplo está aquí: http://pixelbirthcloud.com/574_orig.jpg

no arroja ninguna excepción. la longitud del archivo cargado es el mismo que el original ... intentado cambiar el tipo de mime a application/octet-stream o eliminarlo en absoluto. intenta jugar con tiempos de espera. aún el mismo resultado. los usuarios finales subieron imágenes corruptas casi todo el tiempo (aunque logré obtener imágenes bronem solo 2 veces) ... el tamaño de la imagen fue de 2.5 megas al principio, pero luego lo reduje a 500-700 kb. no solucionó el problema sin embargo.

no han intentado cambiar la biblioteca de apache ... tal vez sea el problema ... pero por lo que he leído en la red, nadie estaba experimentando esto con la biblioteca httpmime.

¿qué puede ser? estoy completamente perdido ahora :(

la otra cuestión es que los tiempos de espera a veces no funciona

como cuando se trata de esta línea:. HttpResponse resp = mHttpClient.execute (post); y desactivo 3g conexión que sólo espera para como 17-20 minutos en lugar de 3 o 5 segundos .. y sólo entonces se lanza una excepción intentado diferentes métodos como esto:..

 HttpParams params = new BasicHttpParams(); 
     HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
     HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); 
     HttpProtocolParams.setUseExpectContinue(params, false); 
     HttpConnectionParams.setConnectionTimeout(params, 10000); 
     HttpConnectionParams.setSoTimeout(params, 10000); 
     ConnManagerParams.setMaxTotalConnections(params, 5); 
     ConnManagerParams.setTimeout(params, 30000); 

     SchemeRegistry registry = new SchemeRegistry(); 
     registry.register(new Scheme("http",PlainSocketFactory.getSocketFactory(), 80)); 
     registry.register(new Scheme("https",PlainSocketFactory.getSocketFactory(), 80)); 
     ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, registry); 
     HttpClient httpclient = new DefaultHttpClient(manager, params); 

pero aún no funciona :)

Respuesta

7

Mira mi Code of Image Uploader y me funcionó muy bien Esta clase carga un archivo en el servidor y al final también lee la respuesta XML. Filtrar el código como por su exigencia .. Se trabajó muy suave para mí


package com.classifieds; 

import java.io.DataOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 

import java.net.HttpURLConnection; 
import java.net.MalformedURLException; 
import java.net.URL; 

import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 

import org.xml.sax.Attributes; 
import org.xml.sax.InputSource; 
import org.xml.sax.SAXException; 
import org.xml.sax.XMLReader; 
import org.xml.sax.helpers.DefaultHandler; 


import android.util.Log; 

public class Uploader 
{ 

    private String Tag = "UPLOADER"; 
    private String urlString ;//= "YOUR_ONLINE_PHP"; 
    HttpURLConnection conn; 
    String exsistingFileName ; 

    private void uploadImageData(String existingFileName , String urlString) 
    { 
     String lineEnd = "\r\n"; 
     String twoHyphens = "--"; 
     String boundary = "*****"; 
     try { 
      // ------------------ CLIENT REQUEST 

      Log.e(Tag, "Inside second Method"); 

      FileInputStream fileInputStream = new FileInputStream(new File(
        exsistingFileName)); 

      // open a URL connection to the Servlet 

      URL url = new URL(urlString); 

      // Open a HTTP connection to the URL 

      conn = (HttpURLConnection) url.openConnection(); 

      // Allow Inputs 
      conn.setDoInput(true); 

      // Allow Outputs 
      conn.setDoOutput(true); 

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

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

      dos.writeBytes(twoHyphens + boundary + lineEnd); 
      dos 
        .writeBytes("Content-Disposition: post-data; name=uploadedfile;filename=" 
          + exsistingFileName + "" + lineEnd); 
      dos.writeBytes(lineEnd); 

      Log.v(Tag, "Headers are written"); 

      // create a buffer of maximum size 

      int bytesAvailable = fileInputStream.available(); 
      int maxBufferSize = 1000; 
      // int bufferSize = Math.min(bytesAvailable, maxBufferSize); 
      byte[] buffer = new byte[bytesAvailable]; 

      // read file and write it into form... 

      int bytesRead = fileInputStream.read(buffer, 0, bytesAvailable); 

      while (bytesRead > 0) { 
       dos.write(buffer, 0, bytesAvailable); 
       bytesAvailable = fileInputStream.available(); 
       bytesAvailable = Math.min(bytesAvailable, maxBufferSize); 
       bytesRead = fileInputStream.read(buffer, 0, bytesAvailable); 
      } 

      // send multipart form data necesssary after file data... 

      dos.writeBytes(lineEnd); 
      dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); 

      // close streams 
      Log.v(Tag, "File is written"); 
      fileInputStream.close(); 
      dos.flush(); 
      dos.close(); 

     } catch (MalformedURLException ex) { 
      Log.e(Tag, "error: " + ex.getMessage(), ex); 
     } 

     catch (IOException ioe) { 
      Log.e(Tag, "error: " + ioe.getMessage(), ioe); 
     } 


     SAXParserFactory spf = SAXParserFactory.newInstance(); 
     SAXParser sp = null; 
     try { 
      sp = spf.newSAXParser(); 
     } catch (ParserConfigurationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (SAXException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     // Get the XMLReader of the SAXParser we created. 
     XMLReader xr = null; 
     try { 
      xr = sp.getXMLReader(); 
     } catch (SAXException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     // Create a new ContentHandler and apply it to the XML-Reader 
     MyExampleHandler1 myExampleHandler = new MyExampleHandler1(); 
     xr.setContentHandler(myExampleHandler); 

     // Parse the xml-data from our URL. 
     try { 
      xr.parse(new InputSource(conn.getInputStream())); 
     //xr.parse(new InputSource(new java.io.FileInputStream(new java.io.File("login.xml")))); 
     } catch (MalformedURLException e) { 
      Log.d("Net Disconnected", "NetDisconeeted"); 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      Log.d("Net Disconnected", "NetDisconeeted"); 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (SAXException e) { 
      Log.d("Net Disconnected", "NetDisconeeted"); 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     // Parsing has finished. 

    } 

    public Uploader(String existingFileName, boolean isImageUploading , String urlString) { 

     this.exsistingFileName = existingFileName; 
     this.urlString = urlString; 

    } 

    class MyExampleHandler1 extends DefaultHandler 
    { 
    // =========================================================== 
    // Methods 
    // =========================================================== 

    @Override 
    public void startDocument() throws SAXException { 

    } 

    @Override 
    public void endDocument() throws SAXException { 
     // Nothing to do 
    } 

    @Override 
    public void startElement(String namespaceURI, String localName, 
       String qName, Attributes atts) throws SAXException { 


    } 

    /** Gets be called on closing tags like: 
    * </tag> */ 
    @Override 
    public void endElement(String namespaceURI, String localName, String qName) 
       throws SAXException { 


    } 

    /** Gets be called on the following structure: 
    * <tag>characters</tag> */ 
    @Override 
    public void characters(char ch[], int start, int length) { 

    } 
    } 

} 
+0

El script en línea que aparecerá debe tener el código para leer el archivo y guardarlo en la base de datos. – Javanator

+0

puede terminar haciendo algo como esto, supongo ... aunque no contestó la pregunta, pero gracias. Vi esa solución en la red antes, pero decidió ir de una manera más conveniente - usando httpcomponents ... pero falló por alguna razón :( – Alex

+0

es una clase completa solo necesitamos pasar la url de archivo y la url de script. ¿Qué sería más conveniente entonces? esta – Javanator

1

bien. pasó 2 días probando este problema y descubrió lo siguiente:
cuando se usa tcpdump en Android, los datos no estaban corruptos, PERO el tamaño del paquete tcp era 1516, lo cual es muy extraño, porque el tamaño normal del paquete de Ethernet es 1500 y todo más de 1516 es demasiado grande.
cambié manualmente el MTU a 576 (creo que es el estándar para ppp, que en realidad es 3G) y ¡funciona perfecto! 150 de 150 imágenes fueron cargadas normalmente!

esto no resuelve el problema real, sin embargo, porque es imposible cambiar el mtu en dispositivos no rooteados, creo, y debe cambiarlo cada vez que reinicie el dispositivo (o cada vez que aparezca la interfaz - No estoy seguro, porque no pude encontrar la forma de obtener el valor de MTU a través de ifconfig. pero al menos sé dónde está el problema.
configurando el tamaño del fragmento http a un valor menor (intenté 300 bytes) no lo afectó (creo que es porque los encabezados http son demasiado grandes) ... así que ...así que nada =)

tratará de publicarla en grupo android-desarrollador de Google, pero su moderación es demasiado lento ... ya veremos ...

+0

Hola Alex, creo que estoy teniendo un problema similar al tuyo, pero no he verificado con tcpdump como lo hiciste. Estoy usando httpclient y lo que he hecho es establecer una suma de comprobación en los datos que envía el cliente, en el lado del servidor, la suma de comprobación es incorrecta en las ocasiones en que experimentamos este problema. en mi caso, los datos cargados parecen simplemente faltar partes del archivo. otras veces todo funciona a la perfección. Vi tu hilo en desarrolladores de Android pero no parecía que hayas encontrado una solución. cualquier cosa nueva para informar (¡por favor!) – dweebo

+0

si faltan partes del archivo, este es otro problema. si usa mediastore, debe buscar errores de froyo con una longitud de archivo incorrecta.porque si la longitud del archivo en el servidor es diferente, pero todavía recibe el archivo, significa que la longitud del contenido es incorrecta, de otra manera simplemente rechazaría la carga debido a la diferente longitud del archivo ... – Alex

+0

Gracias Alex, nosotros hemos verificado que los datos creados por la aplicación son correctos, pero la versión que recibimos en el servidor es incorrecta. el tamaño del archivo ES diferente. no estamos usando mediastore, por lo que el error froyo no es nuestro problema, es otra cosa. verificado que esto solo ocurre con Android 2.2+, pero en una variedad de teléfonos y operadores y le está sucediendo a cientos de nuestros usuarios – dweebo

4

que tenían el mismo problema de la corrupción en el 80 % de mis archivos cargados Emulator no dejó de cargar sin embargo. Los archivos corruptos eran 1k más grandes que los originales. Luego configuré el buffer de la secuencia de salida en 1 byte y comenzó a funcionar sin problemas. Finalmente lo dejé en 8 bytes y no tuve más problemas de corrupción. Un búfer de aproximadamente 80 o 50, no lo recuerdo, también falló. No entiendo cuál es el problema, pero estoy feliz de que funcione de esta manera. Esta página fue muy inspiradora gracias.

Cuestiones relacionadas