我试图在我的下载管理器中实现暂停/恢复,我搜索网络并阅读几篇文章并根据它们更改我的代码,但简历似乎不能正常工作,有什么想法吗?
if (!downloadPath.exists())
downloadPath.mkdirs();
if (outputFileCache.exists())
{
downloadedSize = outputFileCache.length();
connection.setAllowUserInteraction(true);
connection.setRequestProperty("Range", "bytes=" + downloadedSize + "-");
connection.setConnectTimeout(14000);
connection.connect();
input = new BufferedInputStream(connection.getInputStream());
output = new FileOutputStream(outputFileCache, true);
input.skip(downloadedSize); //Skip downloaded size
}
else
{
connection.setConnectTimeout(14000);
connection.connect();
input = new BufferedInputStream(url.openStream());
output = new FileOutputStream(outputFileCache);
}
fileLength = connection.getContentLength();
byte data[] = new byte[1024];
int count = 0;
int __progress = 0;
long total = downloadedSize;
while ((count = input.read(data)) != -1 && !this.isInterrupted())
{
total += count;
output.write(data, 0, count);
__progress = (int) (total * 100 / fileLength);
}
output.flush();
output.close();
input.close();
问题解决了,下面是我为其他想要实现暂停/恢复的用户编写的代码:
if (outputFileCache.exists())
{
connection.setAllowUserInteraction(true);
connection.setRequestProperty("Range", "bytes=" + outputFileCache.length() + "-");
}
connection.setConnectTimeout(14000);
connection.setReadTimeout(20000);
connection.connect();
if (connection.getResponseCode() / 100 != 2)
throw new Exception("Invalid response code!");
else
{
String connectionField = connection.getHeaderField("content-range");
if (connectionField != null)
{
String[] connectionRanges = connectionField.substring("bytes=".length()).split("-");
downloadedSize = Long.valueOf(connectionRanges[0]);
}
if (connectionField == null && outputFileCache.exists())
outputFileCache.delete();
fileLength = connection.getContentLength() + downloadedSize;
input = new BufferedInputStream(connection.getInputStream());
output = new RandomAccessFile(outputFileCache, "rw");
output.seek(downloadedSize);
byte data[] = new byte[1024];
int count = 0;
int __progress = 0;
while ((count = input.read(data, 0, 1024)) != -1
&& __progress != 100)
{
downloadedSize += count;
output.write(data, 0, count);
__progress = (int) ((downloadedSize * 100) / fileLength);
}
output.close();
input.close();
}
如果没有更多的信息是不可能判断出什么是错误的,但是需要注意的是:
- 你必须发出一个HTTP/1.1请求(很难从你的示例代码中分辨出来)
- 服务器必须支持HTTP/1.1
- 服务器将在响应 中通过Accept-Ranges报头告诉你它支持什么
- If-Range应该是服务器给你的资源的etag,而不是最后修改的时间
你应该用一些简单的东西来检查你的范围请求,以测试原点实际上首先支持范围请求(如curl或wget)
可能是您的服务器响应时间过长(超过超时限制),或者这也是一个事实,并非所有服务器都支持暂停-恢复。文件是通过Http、https、ftp还是udp下载的,这也是需要考虑的一点。
pause "可能只是意味着读取一些流并将其写入磁盘。当你继续下载时,你必须使用标题来指定剩下的内容。
你可以尝试这样做:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
if(ISSUE_DOWNLOAD_STATUS.intValue()==ECMConstant.ECM_DOWNLOADING){
File file=new File(DESTINATION_PATH);
if(file.exists()){
downloaded = (int) file.length();
connection.setRequestProperty("Range", "bytes="+(file.length())+"-");
}
}else{
connection.setRequestProperty("Range", "bytes=" + downloaded + "-");
}
connection.setDoInput(true);
connection.setDoOutput(true);
progressBar.setMax(connection.getContentLength());
in = new BufferedInputStream(connection.getInputStream());
fos=(downloaded==0)? new FileOutputStream(DESTINATION_PATH): new FileOutputStream(DESTINATION_PATH,true);
bout = new BufferedOutputStream(fos, 1024);
byte[] data = new byte[1024];
int x = 0;
while ((x = in.read(data, 0, 1024)) >= 0) {
bout.write(data, 0, x);
downloaded += x;
progressBar.setProgress(downloaded);
}
请尽量同步。
我将从这行开始调试:
connection.setRequestProperty("Range", "bytes=" + downloadedSize + "-");
由于无法从源代码中确定downloadedSize
是什么,因此很难进一步详细说明,但格式应该是bytes=from-to
。
无论如何,我建议您使用Apache HttpClient来避免常见的陷阱。这是一个使用Apache HttpClient的人在类似主题上的问题,并提供了一些示例代码。
我认为你只需要删除input.skip(downloadsize)行。设置HTTP报头的字节范围意味着服务器将跳过发送这些字节。
假设您有一个由"aaaaabbbbbcccccddddd"组成的20字节长的文件,并假设在下载5个字节后暂停传输。然后Range报头将导致服务器发送"bbbbbcccccddddd",您应该读取所有内容并将其附加到文件中——不要跳过()。但是代码中的skip()调用将跳过"bbbbb",留下"cccccddddd"等待下载。如果您已经下载了至少50%的文件,那么skip()将耗尽所有输入,并且不会发生任何事情。
同样,stringy05的帖子中的所有内容都适用。您应该确保服务器支持HTTP/1.1,确保资源支持Range标头(动态生成的内容可能不支持它),并确保资源没有使用etag和修改日期进行修改。