Подтвердить что ты не робот

Реализация паузы/возобновления загрузки файла

Я пытаюсь реализовать pause/resume в моем менеджере загрузки, я ищу в Интернете и читаю несколько статей и меняю свой код по ним, но возобновление кажется неправильным, любые идеи?

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

Ответ 1

Хорошо исправлена ​​проблема, вот мой код для других пользователей, которые хотят реализовать 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();
       }

Ответ 2

Невозможно сказать, что не так, без какой-либо дополнительной информации, однако следует отметить:

  • Вы должны сделать запрос HTTP/1.1 (это сложно сказать из вашего примера кода)
  • Сервер должен поддерживать HTTP/1.1
  • Сервер сообщит вам, что он поддерживает, с заголовком Accept-Ranges в ответе
  • If-Range должен быть этагом, который сервер предоставил вам для ресурса, а не последним измененным временем

Вы должны проверить свой запрос диапазона на что-то простое, чтобы проверить происхождение, фактически поддерживает запрос диапазона сначала (например, curl или wget).

Ответ 3

Я бы начал отладку из этой строки:

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

Как из исходного кода невозможно определить, что такое downloadedSize, его сложно уточнить, но формат должен быть bytes=from-to.

В любом случае, я предлагаю вам использовать Apache HttpClient, чтобы избежать распространенных ошибок. Здесь - вопрос от кого-то, кто использует Apache HttpClient по аналогичной теме, и предоставляется некоторый пример кода.

Ответ 4

Возможно, ваш сервер долго реагирует (более чем на ограничение тайм-аута), или это также факт, что не все серверы поддерживают паузу-возобновление. Также стоит подумать, что погода загружается через Http, https, ftp или udp.

Pausing "может означать только чтение некоторого потока и запись его на диск. При возобновлении вам придется использовать заголовки, чтобы указать, что осталось скачать.

вы можете попробовать что-то вроде:

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

и попробуйте синхронизировать вещи.

Ответ 5

Мне кажется, вам просто нужно удалить строку input.skip(downloadSize). Настройка HTTP-заголовка для диапазона байтов означает, что сервер пропустит отправку этих байтов.

Скажем, у вас есть файл длиной 20 байт, состоящий из "aaaaabbbbbcccccddddd", и предположим, что перенос приостанавливается после загрузки 5 байтов. Тогда заголовок Range заставит сервер отправлять "bbbbbccccccddddd", вы должны прочитать все это содержимое и добавить его в файл - без skip(). Но вызов skip() в вашем коде пропускает "bbbbb", оставляя "cccccddddd" для загрузки. Если вы уже загрузили не менее 50% файла, то skip() исчерпает все входные данные и ничего не произойдет.

Кроме того, применяются все вещи в postty05 post. Вы должны убедиться, что сервер поддерживает HTTP/1.1, убедитесь, что заголовок Range поддерживается для ресурса (динамически созданный контент может его не поддерживать) и убедитесь, что ресурс не модифицирован с помощью etag и даты изменения.