Reprendre le téléchargement de fichiers http en java

URL url = new URL("http://download.thinkbroadband.com/20MB.zip");

URLConnection connection = url.openConnection();
File fileThatExists = new File(path); 
OutputStream output = new FileOutputStream(path, true);
connection.setRequestProperty("Range", "bytes=" + fileThatExists.length() + "-");

connection.connect();

int lenghtOfFile = connection.getContentLength();

InputStream input = new BufferedInputStream(url.openStream());
byte data[] = new byte[1024];

long total = 0;

while ((count = input.read(data)) != -1) {
    total += count;

    output.write(data, 0 , count);
}

dans ce code, j'essaie de reprendre le téléchargement. Le fichier cible est de 20 Mo. Mais quand j'arrête le téléchargement sur 10mb, puis contunue, j'obtiens le fichier avec 30MB filesize. Il semble qu'il continue à écrire au dossier, mais ne peut pas en partie télécharger à partir du serveur. Wget -c fonctionne très bien avec ce fichier. Comment puis-je reprendre le téléchargement de fichier?

54
demandé sur om-nom-nom 2011-06-04 17:45:21

7 réponses

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

ce n'est pas mon code, mais ça marche.

57
répondu POMATu 2011-06-12 16:21:44

je suppose que le problème auquel vous êtes confrontés est d'appeler url.openStream() après url.openConnection() .

url.openStream() est équivalent à url.openConnection().getInputStream() . Par conséquent, vous demandez l'url deux fois. En particulier la deuxième fois, il ne spécifie pas la propriété range. Par conséquent, le téléchargement commence toujours au début.

remplacer url.openStream() par connection.getInputStream() .

16
répondu user1084090 2014-05-28 08:53:08

Check out ce fil qui a un problème similaire au vôtre . Si wget fonctionne, alors le serveur soutient clairement la reprise des téléchargements. Il semble que vous ne positionnez pas l'en-tête If-Range comme mentionné dans la réponse acceptée du lien ci-dessus. IE. ajouter:

// Initial download.
String lastModified = connection.getHeaderField("Last-Modified");

// ...

// Resume download.
connection.setRequestProperty("If-Range", lastModified); 
3
répondu Mark Fisher 2017-05-23 12:18:07

puisque la question est marquée avec Android: Avez-vous essayé d'utiliser DownloadManager . Il gère tout ça gentiment pour toi.

1
répondu koljaTM 2014-03-13 09:16:20

et ça?

public static void download(DownloadObject object) throws IOException{
    String downloadUrl = object.getDownloadUrl();
    String downloadPath = object.getDownloadPath();
    long downloadedLength = 0;

    File file = new File(downloadPath);
    URL url = new URL(downloadUrl);

    BufferedInputStream inputStream = null;
    BufferedOutputStream outputStream = null;

    URLConnection connection = url.openConnection();

    if(file.exists()){
        downloadedLength = file.length();
        connection.setRequestProperty("Range", "bytes=" + downloadedLength + "-");
        outputStream = new BufferedOutputStream(new FileOutputStream(file, true));

    }else{
        outputStream = new BufferedOutputStream(new FileOutputStream(file));

    }

    connection.connect();

    inputStream = new BufferedInputStream(connection.getInputStream());


    byte[] buffer = new byte[1024*8];
    int byteCount;

    while ((byteCount = inputStream.read(buffer)) != -1){
        outputStream.write(buffer, 0, byteCount);
        break;

    }

    inputStream.close();
    outputStream.flush();
    outputStream.close();

}

utilisé break; pour tester le code.. ;)

1
répondu Udara 2016-08-26 18:37:49

c'est ce que j'utilise pour télécharger le fichier in chunk mettant à jour l'UI avec progress.

/ ** @param callback = pour mettre à jour L'interface utilisateur avec l'action appropriée

 * @param fileName = Name of the file by which downlaoded file will be saved.
 * @param downloadURL = File downlaoding URL
 * @param filePath = Path where file will be saved
 * @param object = Any object you want in return after download is completed to do certain operations like insert in DB or show toast
 */

public void startDownload(final IDownloadCallback callback, String fileName, String downloadURL, String filePath, Object object) {
    callback.onPreExecute(); // Callback to tell that the downloading is going to start
    int count = 0;
    File outputFile = null; // Path where file will be downloaded
    try {
        File file = new File(filePath);
        file.mkdirs();
        long range = 0;
        outputFile = new File(file, fileName);
        /**
         * Check whether the file exists or not
         * If file doesn't exists then create the new file and range will be zero.
         * But if file exists then get the length of file which will be the starting range,
         * from where the file will be downloaded
         */
        if (!outputFile.exists()) {
            outputFile.createNewFile();
            range = 0;
        } else {
            range = outputFile.length();
        }
        //Open the Connection
        URL url = new URL(downloadURL);
        URLConnection con = url.openConnection();
        // Set the range parameter in header and give the range from where you want to start the downloading
        con.setRequestProperty("Range", "bytes=" + range + "-");
        /**
         * The total length of file will be the total content length given by the server + range.
         * Example: Suppose you have a file whose size is 1MB and you had already downloaded 500KB of it.
         * Then you will pass in Header as "Range":"bytes=500000".
         * Now the con.getContentLength() will be 500KB and range will be 500KB.
         * So by adding the two you will get the total length of file which will be 1 MB
         */
        final long lenghtOfFile = (int) con.getContentLength() + range;

        FileOutputStream fileOutputStream = new FileOutputStream(outputFile, true);
        InputStream inputStream = con.getInputStream();

        byte[] buffer = new byte[1024];

        long total = range;
        /**
         * Download the save the content into file
         */
        while ((count = inputStream.read(buffer)) != -1) {
            total += count;
            int progress = (int) (total * 100 / lenghtOfFile);
            EntityDownloadProgress entityDownloadProgress = new EntityDownloadProgress();
            entityDownloadProgress.setProgress(progress);
            entityDownloadProgress.setDownloadedSize(total);
            entityDownloadProgress.setFileSize(lenghtOfFile);
            callback.showProgress(entityDownloadProgress);
            fileOutputStream.write(buffer, 0, count);
        }
        //Close the outputstream
        fileOutputStream.close();
        // Disconnect the Connection
        if (con instanceof HttpsURLConnection) {
            ((HttpsURLConnection) con).disconnect();
        } else if (con instanceof HttpURLConnection) {
            ((HttpURLConnection) con).disconnect();
        }
        inputStream.close();
        /**
         * If file size is equal then return callback as success with downlaoded filepath and the object
         * else return failure
         */
        if (lenghtOfFile == outputFile.length()) {
            callback.onSuccess(outputFile.getAbsolutePath(), object);
        } else {
            callback.onFailure(object);
        }
    } catch (Exception e) {
        e.printStackTrace();
        callback.onFailure(object);
    }
}

interface IDownloadCallback {

    void onPreExecute(); // Callback to tell that the downloading is going to start
    void onFailure(Object o); // Failed to download file
    void onSuccess(String path, Object o); // Downloaded file successfully with downloaded path
    void showProgress(EntityDownloadProgress entityDownloadProgress); // Show progress
}

public class EntityDownloadProgress {

    int progress; // range from 1-100
    long fileSize;// Total size of file to be downlaoded
    long downloadedSize; // Size of the downlaoded file

    public void setProgress(int progress) {this.progress = progress;}

    public void setFileSize(long fileSize) {this.fileSize = fileSize;}

    public void setDownloadedSize(long downloadedSize) {this.downloadedSize = downloadedSize;}
}
1
répondu Ankit Kumar 2018-06-05 05:21:53

j'ai un moyen pour que votre code fonctionne.

  1. d'abord, vérifiez si le fichier existe ou non
  2. si le fichier existe, définissez la connexion:

    connection.setRequestProperty("Range", "bytes=" + bytedownloaded + "-");
    
  3. si le fichier n'existe pas, faites le même téléchargement dans un nouveau fichier.

1
répondu user3091759 2018-07-30 09:23:49