Android:“Unexpected end of stream”异常下载大文件
Posted
技术标签:
【中文标题】Android:“Unexpected end of stream”异常下载大文件【英文标题】:Android:"Unexpected end of stream" exception downloading large files 【发布时间】:2011-11-16 04:19:18 【问题描述】:我正在构建一个 android 应用程序,我需要从一个 33 MB 大的 url 下载文件。
这里是下载任务:
try
int MAX_BUFFER_SIZE = 4096;
URL mUrl = new URL(params[0]);
HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection();
connection.setRequestMethod("GET");
long length = connection.getContentLength(), downloaded = 0;
int read;
byte [] buffer = new byte[(((int)length) > MAX_BUFFER_SIZE) ? MAX_BUFFER_SIZE : (int)length];
String filename = getFilename(mUrl);
File file = new File (SDCARD_ROOT);
if (!file.exists() || !file.isDirectory())
file.mkdir();
this.filename = filename;
file = new File (SDCARD_ROOT + this.filename);
FileOutputStream fos = new FileOutputStream (file);
//Start downloading
InputStream stream = connection.getInputStream();
while ((read=stream.read(buffer)) > -1)
fos.write(buffer, 0, read);
downloaded += read;
publishProgress((int) ((float) downloaded/length * 100));
fos.close();
return 1;
catch (Exception e)
Log.e("REV-PARTS", "Revolver parts error in DownloadTask: " + e.getMessage());
return 2;
它适用于小文件 (1-15 MB),但对于大文件,它会返回“意外的流结束”异常。
【问题讨论】:
哪个调用会引发异常?stream.read()
?
@Gnufabio 你能解决这个问题吗?
发件人意外关闭了连接。除了删除部分下载之外,您对此无能为力。注意你不需要计算缓冲区大小的所有垃圾。只需使用 8192。将其与数据大小相关联没有任何优势。您的代码仍然可以工作。
你有什么答案吗?你能帮我吗
这似乎是 Android Emulator for Windows 中的一个错误。在 Mac OS 上的 Device 和 Android Emulator 中同样可以正常工作
【参考方案1】:
对于大文件,您需要使用以下代码手动设置连接超时。 我已将超时设置为 3 分钟
connection.setConnectTimeout(180000);
connection.setReadTimeout(180000);
【讨论】:
这将如何解决“流的意外结束”问题? 下载时由于超时出现此错误, 不,不会,也不会。【参考方案2】:我有一个答案。 你应该为你的连接添加一个标题。
connection.setRequestProperty("Accept-Encoding", "identity");
这会对你有帮助。如果有帮助,请说我......
【讨论】:
【参考方案3】:设置块大小似乎对我有用。
connection.setChunkedStreamingMode(1048576);
【讨论】:
在 Android 9 上对我没有帮助,仍然随机出现“Unexpected end of stream”【参考方案4】:当你捕获异常时,我尝试downContinue()
方法。我可以显示我的代码:
private void downloadApk()
thread1 = new Thread()
public void run()
File oFile = null;
try
URL url = new URL(PQGLApplication.resrootURL + "apk/PQGLMap.apk");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
ReadableByteChannel channel =
Channels.newChannel(urlConnection.getInputStream());
oFile =
new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/" + "hy_ht_new/" + "test2" + ".apk");
oFile.setWritable(true);
oFile.setReadable(true);
if (oFile.exists())
oFile.delete();
FileOutputStream fos = new FileOutputStream(oFile);
fileSize = urlConnection.getContentLength();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int noOfBytes = 0;
byte[] data = null;
sendApkMessage(0, 0);
while ((noOfBytes = channel.read(buffer)) > 0)
data = new byte[noOfBytes];
System.arraycopy(buffer.array(), 0, data, 0, noOfBytes);
buffer.clear();
fos.write(data, 0, noOfBytes);
downLoadFileSize += noOfBytes;
sendApkMessage(1, downLoadFileSize);
fos.flush();
fos.close();
channel.close();
sendApkMessage(2, oFile.getAbsolutePath());
catch (Exception e)
// TODO Auto-generated catch block
e.printStackTrace();
downContinue();
;
;
thread1.start();
private void downContinue()
continueTime++;
try
if (continueTime == 3)
continueTime = 0;
sendApkMessage(4, 0);
Log.e("what is the continuetime", "continueTime" + continueTime);
else
URL url = new URL(PQGLApplication.resrootURL + "apk/PQGLMap.apk");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
File oFile =
new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/"
+ "hy_ht_new/" + "test2" + ".apk");
RandomAccessFile oSavedFile = new RandomAccessFile(oFile, "rw");
FileOutputStream fos = new FileOutputStream(oFile);
ReadableByteChannel channel = Channels.newChannel(urlConnection.getInputStream());
// oSavedFile.seek(nPos);
ByteBuffer buffer = ByteBuffer.allocate(1024);
byte[] data = null;
int temp = 0;
sendApkMessage(3, oFile.getAbsolutePath());
while ((temp = channel.read(buffer)) > 0)
data = new byte[temp];
System.arraycopy(buffer.array(), 0, data, 0, temp);
buffer.clear();
fos.write(data, 0, temp);
fos.flush();
fos.close();
oSavedFile.close();
sendApkMessage(2, oFile.getAbsolutePath());
continueTime = 0;
catch (Exception e)
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("what is the exception", e.toString() + continueTime);
downContinue();
这个downContinue
方法就是用来解决这个问题的。至少,文件下载成功!
【讨论】:
你能解释一下 sendApkMessage() 方法,它到底在做什么? 您不需要将输出文件设置为可读或可写或如果存在则预先删除它。new FileOutputStream()
已经具备所有这些效果。你也不需要System.arraycopy()
。方法依赖于未指定的外部代码。以上是关于Android:“Unexpected end of stream”异常下载大文件的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )