2010-08-01 7 views
0

Je suis en train de télécharger un fichier zip en utilisant HttpClient 4 et il se situe autour de 0,5 (kilo-octets/kilobits)? par minute. Le fichier est moins d'un Mo de large, et le téléchargement prendra probablement une heure! Est-ce que je fais quelque chose de mal? Sinon, comment devrais-je faire cela? Voici ma mise en œuvre actuelle:Apache HttpClient dans Android téléchargement extrêmement lent pièce jointe

@Override 
      protected Uri doInBackground(String... params) { 
       publishProgress("Downloading..."); 
       try { 
         HttpPost searchPOST = new HttpPost("http://www.somesite.com/" + searchResult.getURLSuffix()); 
         List<NameValuePair> formparams = new ArrayList<NameValuePair>(); 
         //added parameters here... 
         UrlEncodedFormEntity paramsEntity = new UrlEncodedFormEntity(formparams, HTTP.UTF_8); 
         searchPOST.setEntity(paramsEntity); 


       HttpResponse manualResponse = client.execute(searchPOST); 

       Header fileNameHeader = manualResponse.getFirstHeader("Content-Disposition"); 
       Pattern p = Pattern.compile("filename=\"(.+?)\""); 
       Matcher m = p.matcher(fileNameHeader.getValue()); 

       if (m.find()) { 
        String fileName = m.group(1); 
        InputStream zipStream = manualResponse.getEntity().getContent(); 
        File cacheDir = context.getCacheDir(); 
        String tempFileForZip = cacheDir.getAbsolutePath() + "/" + fileName; 
        FileOutputStream fos = new FileOutputStream(tempFileForZip); 
        int bytesDownloaded = 0; 
        try { 
         int c; 
         while ((c = zipStream.read()) != -1) { 
          fos.write(c); 
          bytesDownloaded++; 
          kilobytesDownloaded=(bytesDownloaded/1000); 
          publishProgress((String[])null); 
         } 
        } finally { 
         if (zipStream != null) { 
          zipStream.close(); 
         } 
         if (fos != null) { 
          fos.close(); 
         } 
        } 

        fos.close(); 


       String zipFilePath = tempFileForZip; 

       //Change to indeterminate 
       kilobytesDownloaded = fileSize; 
       publishProgress("Extracting..."); 

       //TODO: Preferences for save directory 
       saveDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "Downloads/"); 
       ZipTools.unzipArchive(new File(zipFilePath), saveDirectory); 

       } 

        } catch (IllegalStateException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } catch (IOException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } finally { 

        } 

       return Uri.fromFile(saveDirectory); 
     } 

Répondre

7

Étape 1: n'appelez pas publishProgress() pour chaque octet.

Étape 2: Lire plus d'un octet à la fois. Mieux encore, n'utilisez pas le InputStream directement - utilisez HttpEntity#writeTo() pour que HttpClient écrive vos données dans le fichier de sortie.

+1

@CommonsWare bonne étape # 2, je n'avais jamais remarqué la méthode writeTo avant. J'ai récemment trouvé la raison pour laquelle notre redimensionnement PNG basé sur JAI était si lent sur certaines images - PNGDecoder de Java gonfle et lit les morceaux de zTXt un octet à la fois, ce qui prend environ cinq minutes pour redimensionner une image minuscule. Après avoir recompilé avec une simple correction pour utiliser un tampon d'octets, il est des centaines de fois plus rapide. – Nick

+0

Comment mettre à jour le progrès en utilisant cette méthode? –

+0

@Aymon Fournier: Eh bien, je commencerais par l'étape 1, et je téléchargerais en plus gros morceaux (par exemple 10K). Je ne sais pas comment vous mettriez à jour les progrès en utilisant l'étape n ° 2. – CommonsWare