Android Скачать двоичный файл проблемы
У меня возникли проблемы с загрузкой двоичного файла (видео) в моем приложении из интернета. В 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 ответов:
Я не знаю, если это единственная проблема, но у вас есть классический Java Глюк там: вы не рассчитываете на то, что read () является всегда разрешено возвратить меньше байтов, чем вы просите. Таким образом, ваше чтение может получить менее 1024 байт, но ваша запись всегда записывает ровно 1024 байта, возможно, включая байты из предыдущей итерации цикла.
правильно:
while ( (len1 = in.read(buffer)) > 0 ) { f.write(buffer,0, len1); }возможно более высокая латентность сети или меньшие размеры пакетов 3G на Android усиливают эффект?
new DefaultHttpClient().execute(new HttpGet("http://www.path.to/a.mp4?video")) .getEntity().writeTo( new FileOutputStream(new File(root,"Video.mp4")));
одна проблема заключается в чтении буфера. Если каждое чтение входного потока не является точным кратным 1024, вы скопируете плохие данные. Использование:
byte[] buffer = new byte[1024]; int len1 = 0; while ( (len1 = in.read(buffer)) != -1 ) { f.write(buffer,0, len1); }
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."); } }
я исправил код, основанный на предыдущих обратных связях в этом потоке. Я тестировал с помощью 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(); }удачи Алиреза Агамохаммади
просто используйте метод копирования apache (Apache Commons IO) - преимущество использования Java!
IOUtils.copy(is, os);Не забудьте закрыть потоки в блоке finally:
try{ ... } finally { IOUtils.closeQuietly(is); IOUtils.closeQuietly(os); }
Comments