71 votes

Problèmes de téléchargement de fichiers binaires sur Android

Je rencontre des problèmes pour télécharger un fichier binaire (vidéo) dans mon application depuis l'internet. Dans Quicktime, si je le télécharge directement, il fonctionne bien, mais dans mon application, il y a un problème (même s'ils ont exactement la même apparence dans un éditeur de texte). Voici un exemple :

    URL u = new URL("http://www.path.to/a.mp4?video");
    HttpURLConnection c = (HttpURLConnection) u.openConnection();
    c.setRequestMethod("GET");
    c.setDoOutput(true);
    c.connect();
    FileOutputStream f = new FileOutputStream(new File(root,"Video.mp4"));

    InputStream in = c.getInputStream();

    byte[] buffer = new byte[1024];
    int len1 = 0;
    while ( (len1 = in.read(buffer)) > 0 ) {
         f.write(buffer);
    }
    f.close();

92voto

Ry4an Points 56453

Je ne sais pas si c'est le seul problème, mais il y a un problème classique de Java : Tu ne comptes pas sur le fait que read() est toujours autorisé à renvoyer moins d'octets que ce que vous demandez. Ainsi, votre lecture peut obtenir moins de 1024 octets mais votre écriture écrit toujours exactement 1024 octets, y compris éventuellement les octets de l'itération précédente de la boucle.

Corriger avec :

 while ( (len1 = in.read(buffer)) > 0 ) {
         f.write(buffer,0, len1);
 }

Peut-être que le réseau à latence plus élevée ou les paquets plus petits de la 3G sur Android exacerbent l'effet ?

28voto

njzk2 Points 17085
new DefaultHttpClient().execute(new HttpGet("http://www.path.to/a.mp4?video"))
        .getEntity().writeTo(
                new FileOutputStream(new File(root,"Video.mp4")));

16voto

Clint Points 5864

Un problème est votre lecture du tampon. Si chaque lecture du flux d'entrée n'est pas un multiple exact de 1024, vous copierez de mauvaises données. Utilisez :

byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) != -1 ) {
  f.write(buffer,0, len1);
}

14voto

Abhan Points 2661
 public class download extends Activity {

     private static String fileName = "file.3gp";
     private static final String MY_URL = "Your download url goes here";

     @Override
     public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        try {
            URL url = new URL(MY_URL);
            HttpURLConnection c = (HttpURLConnection) url.openConnection();
            c.setRequestMethod("GET");
            c.setDoOutput(true);
            c.connect();

            String PATH = Environment.getExternalStorageDirectory()
                + "/download/";
            Log.d("Abhan", "PATH: " + PATH);
            File file = new File(PATH);
            if(!file.exists()) {
               file.mkdirs();
            }
            File outputFile = new File(file, fileName);
            FileOutputStream fos = new FileOutputStream(outputFile);
            InputStream is = c.getInputStream();
            byte[] buffer = new byte[1024];
            int len1 = 0;
            while ((len1 = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len1);
            }
            fos.flush();
            fos.close();
            is.close();
        } catch (IOException e) {
            Log.e("Abhan", "Error: " + e);
        }
        Log.i("Abhan", "Check Your File.");
    } 
}

3voto

CPU 100 Points 2269

J'ai corrigé le code en fonction des commentaires précédents sur ce fil. J'ai testé en utilisant eclipse et plusieurs gros fichiers. Cela fonctionne bien. Il suffit de copier et coller ce code dans votre environnement et de changer le chemin http et l'emplacement où vous souhaitez que le fichier soit téléchargé.

try {
    //this is the file you want to download from the remote server
    String path ="http://localhost:8080/somefile.zip";
    //this is the name of the local file you will create
    String targetFileName
        boolean eof = false;
    URL u = new URL(path);
    HttpURLConnection c = (HttpURLConnection) u.openConnection();
    c.setRequestMethod("GET");
    c.setDoOutput(true);
    c.connect();
    FileOutputStream f = new FileOutputStream(new File("c:\\junk\\"+targetFileName));
        InputStream in = c.getInputStream();
        byte[] buffer = new byte[1024];
        int len1 = 0;
        while ( (len1 = in.read(buffer)) > 0 ) {
        f.write(buffer,0, len1);
                 }
    f.close();
    } catch (MalformedURLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (ProtocolException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Bonne chance Alireza Aghamohammadi

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X