webentwicklung-frage-antwort-db.com.de

Implementieren Sie Pause/Wiederaufnahme beim Herunterladen von Dateien

Ich versuche, Pause/Lebenslauf in meinem Download-Manager zu implementieren. Ich durchsuche das Internet und lese mehrere Artikel und ändere meinen Code entsprechend, aber der Lebenslauf scheint nicht richtig zu funktionieren.

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

Okay Problem behoben, hier ist mein Code für andere Benutzer, die Pause/Lebenslauf implementieren möchten:

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

Ohne weitere Informationen ist es nicht möglich zu erkennen, was falsch ist.

  1. Sie müssen eine HTTP/1.1-Anforderung erstellen (dies ist aus Ihrem Beispielcode schwer zu erkennen)
  2. Der Server muss HTTP/1.1 unterstützen
  3. Der Server teilt Ihnen mit einem Accept-Ranges-Header in der Antwort mit, was er unterstützt
  4. Wenn-Range der Wert sein soll, den der Server Ihnen für die Ressource gegeben hat, nicht der letzte Änderungszeitpunkt

Sie sollten Ihre Reichweitenanforderung mit einem einfachen Test überprüfen, der zunächst die Bereichsanforderung unterstützt (wie curl oder wget).

5
stringy05

Es kann sein, dass Ihr Server zu lange braucht, um zu antworten (mehr als das Timeout-Limit), oder dies ist auch eine Tatsache, dass nicht alle Server pause-resume unterstützen .. _ durch http, https, ftp oder udp.

"Anhalten" könnte bedeuten, nur einen Teil des Streams zu lesen und auf die Festplatte zu schreiben. Bei der Wiederaufnahme müssten Sie die Header verwenden, um anzugeben, was übrig bleibt .

sie können etwas versuchen wie:

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

und bitte versuche Dinge zu synchronisieren.

2
Manan Sharma

Ich würde von dieser Zeile aus debuggen:

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

Da aus dem Quellcode nicht herausgefunden werden kann, was downloadedSize ist, ist es schwierig, dies weiter auszuführen, aber das Format sollte bytes=from-to sein.

Wie auch immer, ich würde vorschlagen, dass Sie Apache HttpClient verwenden, um häufige Fallstricke zu vermeiden. Hier ist eine Frage von jemandem, der Apache HttpClient für ein ähnliches Thema verwendet, und es wird ein Beispielcode bereitgestellt.

1
mindas

Ich denke, Sie müssen nur die Zeile input.skip (downloadsSize) löschen. Wenn Sie den HTTP-Header für den Bytebereich festlegen, werden diese Bytes von Serversendend übersprungen.

Angenommen, Sie haben eine Datei mit einer Länge von 20 Bytes, bestehend aus "aaaaabbbbbcccccddddd", und nehmen an, die Übertragung wird nach dem Herunterladen von 5 Bytes angehalten. Dann wird der Range-Header den Server veranlassen, "bbbbbcccccddddd" zu senden. Sie sollten all dieses Inhalts lesen und an die Datei anhängen - no skip (). Beim Aufruf von skip () in Ihrem Code wird jedoch "bbbbb" übersprungen, und "cccccddddd" wird heruntergeladen. Wenn Sie bereits mindestens 50% der Datei heruntergeladen haben, erschöpft überspringen () die gesamte Eingabe, und nichts passiert.

Außerdem gelten alle Dinge in stringy05s Post. Stellen Sie sicher, dass der Server HTTP/1.1 unterstützt, stellen Sie sicher, dass der Range-Header für die Ressource unterstützt wird (dynamisch generierter Inhalt unterstützt sie möglicherweise nicht), und stellen Sie sicher, dass die Ressource nicht mit etag und dem Änderungsdatum geändert wird.

0
picomancer