2009-02-23 123 views
68

我在从我的应用程序从互联网下载二进制文件(视频)时遇到问题。在Quicktime中,如果我直接下载它,它可以正常工作,但通过我的应用程序它会弄乱(即使它们在文本编辑器中看起来完全一样)。以下是一个示例:Android下载二进制文件问题

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

回答

91

我不知道这是否是唯一的问题,但你在那里有一个经典的Java毛刺:你不是对阅读(事实上算起)是总是允许返回的字节数少于您要求的数量。因此,您的读取可能会少于1024个字节,但您的写入总是写出1024个字节,可能包括前一个循环迭代中的字节。

纠正:

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

也许高延迟网络或3G Android上较小的数据包大小加剧的影响?

+4

多么愚蠢的错误......谢谢!这是当你不正确地阅读教程时会发生什么:) – 2009-02-23 05:03:31

+3

谢谢...也帮助了我。 – 2009-07-24 22:11:13

+0

如何初始化缓冲区?怎样防范异常?关于释放资源呢?我认为这是一个好的,但不是一个完整的答案。这里还有其他更完整的答案。 – 2011-06-23 17:04:16

16

一个问题是您读取缓冲区。如果输入流的每次读取都不是1024的精确倍数,则会复制错误的数据。用途:

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

第4行中,你的意思LEN1,不len个? – 2009-02-23 04:52:40

+0

我看Ry4an的例子,并假设你的意思是len1 - 谢谢。 – 2009-02-23 04:59:02

14
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."); 
    } 
} 
2

只需使用apache的复制方法(Apache Commons IO) - 使用Java的优势!

IOUtils.copy(is, os); 

不要忘记关闭流在finally块:

try{ 
     ... 
} finally { 
    IOUtils.closeQuietly(is); 
    IOUtils.closeQuietly(os); 
} 
4

我固定的代码基础,就这个主题之前的反馈。我使用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(); 
} 

好运 阿里Aghamohammadi

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