web-dev-qa-db-fra.com

Android problèmes de téléchargement de fichiers binaires

J'ai des problèmes pour télécharger un fichier binaire (vidéo) dans mon application depuis Internet. Dans Quicktime, si je le télécharge directement, cela fonctionne bien, mais grâce à mon application, il est en quelque sorte foiré (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();
71
Isaac Waller

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

Corriger avec:

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

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

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

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 copiez des données incorrectes. Utilisation:

byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) != -1 ) {
  f.write(buffer,0, len1);
}
16
Clint
 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.");
    } 
}
14
user456118

J'ai corrigé le code en fonction des commentaires précédents sur ce fil. J'ai testé en utilisant Eclipse et plusieurs fichiers volumineux. Cela fonctionne bien. Il vous suffit de copier et coller ceci dans votre environnement et de modifier 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

3
grepit

Utilisez simplement la méthode de copie d'Apache ( Apache Commons IO ) - l'avantage d'utiliser Java!

IOUtils.copy(is, os);

N'oubliez pas de fermer les flux dans un bloc enfin:

try{
      ...
} finally {
  IOUtils.closeQuietly(is);
  IOUtils.closeQuietly(os);
}
2
AlikElzin-kilaka