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();
81292 次浏览

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

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

我不知道这是否是唯一的问题,但是您遇到了一个典型的 Java 故障: 您没有考虑 read ()是 一直都是允许返回的字节数比您要求的少这一事实。因此,您的读取可能少于1024个字节,但是您的写总是写出正好1024个字节,可能包括前一个循环迭代的字节。

正确答案是:

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

也许 Android 上更高的延迟网络或者更小的3G 数据包尺寸正在加剧这种效应?

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

只需使用 apache 的 copy 方法(Apache Commons IO)-使用 Java 的优点!

IOUtils.copy(is, os);

不要忘记关闭 finally 块中的流:

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

我根据以前对这个线程的反馈修改了代码。我使用 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();
}

祝你好运 Alireza Aghamohammadi

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