实现文件下载暂停/恢复(Implement pause/resume in file downloa

2019-07-21 09:07发布

我想实现我的下载管理器暂停/恢复,我在网上搜索并阅读一些文章,并根据他们改变我的代码,但似乎简历无法正常工作,任何想法?

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

Answer 1:

固定好了的问题,这是我的谁想要实现暂停/恢复其他用户的代码:

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


Answer 2:

这是不可能告诉什么是错的没有一些更多的信息,但是要注意的事情:

  1. 你必须做一个HTTP / 1.1请求(很难从你的示例代码来告诉)
  2. 服务器必须支持HTTP / 1.1
  3. 服务器会告诉你它在响应一个Accept-范围头支持
  4. 如果-范围应的eTag服务器给你的资源,而不是最后修改时间

您应该检查简单的东西来测试你的范围内要求源实际支持范围请求第一(如卷曲或wget的)



Answer 3:

它不然是你的服务器正在长回应(更多然后超时限制),或者这也是一个事实,即并非所有的服务器都支持暂停 - 恢复。 这也是思考这个天气的文件通过HTTP,HTTPS,FTP或UDP下载点。

暂停”可能只是意味着读了一些流并将其写入到磁盘中。 当你重新开始将必须使用标头指定剩下来下载

您可以尝试这样的:

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

并请尝试同步的东西。



Answer 4:

我想从这条线开始调试:

connection.setRequestProperty("Range", "bytes=" + downloadedSize + "-");

从源代码是不可能确定什么downloadedSize是,很难进一步阐述,但格式应该是bytes=from-to

无论如何,我会建议你使用的Apache的HttpClient来避免常见的陷阱。 这是从别人谁在类似题目使用Apache的HttpClient并提供一些示例代码的问题。



Answer 5:

我想,你只需要删除input.skip(downloadedSize)线。 设置字节范围的HTTP标头表示服务器将跳过发送这些字节。

假设你有一个文件,该文件是20个字节长组成的“aaaaabbbbbcccccddddd”,并假设转移是下载5个字节后暂停。 然后Range头将导致服务器发送“bbbbbcccccddddd”,你应该阅读所有这些内容,并追加到文件-没有跳过()。 但是,在你的代码跳过()调用将跳过“BBBBB”离开“cccccddddd”被下载。 如果您已经下载的文件的至少50%,然后跳过()会用尽所有的输入和什么都不会发生。

此外,所有的stringy05的帖子的事情适用。 您应该确保服务器支持HTTP / 1.1,确保Range头支持对资源(动态生成的内容可能不支持它),并确保资源使用ETAG和修改日期不会改变。



文章来源: Implement pause/resume in file downloading