Проблемы с загрузкой двоичных файлов на Android - PullRequest
71 голосов
/ 23 февраля 2009

У меня проблемы с загрузкой двоичного файла (видео) в моем приложении из Интернета. В Quicktime, если я загружаю его напрямую, он работает нормально, но через мое приложение он как-то портится (даже если они выглядят точно так же в текстовом редакторе). Вот пример:

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

Ответы [ 6 ]

93 голосов
/ 23 февраля 2009

Я не знаю, единственная ли это проблема, но у вас есть классический сбой Java: вы не рассчитываете на то, что read () всегда позволяет вернуть меньше байтов, чем вы просите. Таким образом, ваше чтение может получить менее 1024 байтов, но ваша запись всегда записывает ровно 1024 байта, возможно, включая байты из предыдущей итерации цикла.

Исправить с помощью:

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

Возможно, более высокая задержка в сети или меньший размер пакетов 3G на Android усиливают эффект?

28 голосов
/ 12 мая 2011
new DefaultHttpClient().execute(new HttpGet("http://www.path.to/a.mp4?video"))
        .getEntity().writeTo(
                new FileOutputStream(new File(root,"Video.mp4")));
16 голосов
/ 23 февраля 2009

Одной из проблем является ваше чтение буфера. Если каждое чтение входного потока не является точным кратным 1024, вы скопируете неверные данные. Использование:

byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) != -1 ) {
  f.write(buffer,0, len1);
}
14 голосов
/ 10 декабря 2010
 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.");
    } 
}
4 голосов
/ 20 апреля 2011

Я исправил код на основе предыдущих отзывов в этой теме. Я тестировал с использованием Eclipse и нескольких больших файлов. Работает нормально. Просто скопируйте и вставьте его в свою среду и измените http-путь и местоположение, куда вы хотите загрузить файл.

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();
}

Удачи Алиреза Агамохаммади

2 голосов
/ 20 апреля 2011

Просто используйте метод копирования apache ( Apache Commons IO ) - преимущество использования Java!

IOUtils.copy(is, os);

Не забудьте закрыть потоки в блоке finally:

try{
      ...
} finally {
  IOUtils.closeQuietly(is);
  IOUtils.closeQuietly(os);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...