Zaimplementuj wstrzymanie / wznowienie pobierania plików

Próbuję zaimplementować pauzę/wznowienie w moim menedżerze pobierania, przeszukuję Sieć i czytam kilka artykułów i zmieniam kod zgodnie z nimi, ale resume wydaje się nie działać poprawnie, jakieś pomysły?

                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();
Author: NullPointer, 2013-03-11

5 answers

Ok problem rozwiązany, Oto Mój kod dla innych użytkowników, którzy chcą zaimplementować pause/resume:

        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();
       }
 20
Author: NullPointer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-21 19:29:53

Nie można powiedzieć, co jest nie tak bez więcej informacji, jednak rzeczy do zauważenia:

  1. musisz złożyć żądanie HTTP / 1.1 (trudno powiedzieć z przykładowego kodu)
  2. serwer musi obsługiwać HTTP/1.1
  3. Serwer powie Ci, co Obsługuje z nagłówkiem Accept-Ranges w odpowiedzi
  4. If-Range powinien być etagiem podanym przez serwer dla zasobu, a nie ostatnim czasem modyfikacji

Należy sprawdzić Zapytanie o zasięg z coś prostego do przetestowania origin faktycznie obsługuje najpierw żądanie zakresu (jak curl lub wget)

 5
Author: stringy05,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-13 03:14:43

Nie może być tak, że twój serwer długo reaguje (więcej niż limit czasu oczekiwania) lub jest to również fakt, że nie wszystkie serwery obsługują pause - resume. Warto również zastanowić się, czy plik jest pobierany przez Http, https, ftp lub udp.

Pauzowanie " może po prostu oznaczać odczytanie części strumienia i zapisanie go na dysk. podczas wznawiania musisz użyć nagłówków, aby określić, co pozostało do pobrania .

Możesz spróbować czegoś takiego :

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

I proszę spróbować zsynchronizować rzeczy.

 2
Author: Manan Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-21 13:28:25

Chciałbym rozpocząć debugowanie od tej linii:

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

Ponieważ z kodu źródłowego nie można określić, czym jest downloadedSize, trudno jest rozwinąć dalej, ale format powinien być bytes=from-to.

W każdym razie sugerowałbym użycie Apache HttpClient, aby uniknąć typowych pułapek. Tutaj {[9] } jest pytanie od kogoś, kto używa Apache HttpClient na podobny temat i niektóre przykładowy kod jest dostarczony.

 1
Author: mindas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:08

Myślę, że wystarczy usunąć dane wejściowe.linia skip (downloadedSize). Ustawienie nagłówka HTTP dla zakresu bajtów oznacza, że serwer pominie wysyłanie tych bajtów.

Załóżmy, że masz plik o długości 20 bajtów składający się z "aaaaabbbbbcccddddd" i załóżmy, że transfer zostanie wstrzymany po pobraniu 5 bajtów. Wtedy nagłówek Range spowoduje, że serwer wyśle "bbbbbccccddddd", powinieneś przeczytać całą tej zawartości i dołączyć ją do pliku -- no skip(). Ale wywołanie skip() w Twoim kodzie pominie "bbbbb" pozostawiając "cccccddddd" do pobrania. Jeśli pobrałeś już co najmniej 50% pliku, skip() wyczerpie wszystkie dane wejściowe i nic się nie stanie.

Również wszystkie rzeczy w poście stringy05 mają zastosowanie. Upewnij się, że serwer obsługuje HTTP/1.1, upewnij się, że nagłówek zakresu jest obsługiwany dla zasobu (dynamicznie generowana zawartość może go nie obsługiwać) i upewnij się, że zasób nie jest modyfikowany za pomocą etag i Data modyfikacji.

 0
Author: picomancer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-21 01:55:12