Как возобновить загрузку прерывания с RandomAccessFile? - PullRequest
0 голосов
/ 07 апреля 2020

Я хочу прервать загрузку с RandomAccessFile. Вот код

HttpGet httpget = HttpUtil.buildGet(URL)
httpget.setHeader("RANGE", "bytes=" + (position) + "-");
CloseableHttpResponse response = HttpClients.createDefault().execute(httpget) 
HttpEntity entity = response.getEntity();

int totalLen = 0;
InputStream is = entity.getContent();
RandomAccessFile writeFile = new RandomAccessFile(desc, "rw");
writeFile.seek(position);
byte[] buf = new byte[65536];
totalLen = 0;
int len = is.read(buf);
while (len > 0) {
   totalLen += len;
   writeFile.write(buf);
   len = is.read(buf);
}
response.close();
is.close();
writeFile.close();

HttpRequest возвращает 206, и загрузка успешно завершена, но я получаю неправильный файл, файл намного больше исходного, и я не могу его открыть. Что не так с этим кодом? И как возобновить загрузку прерываний с RandomAccessFile?

1 Ответ

2 голосов
/ 07 апреля 2020

С комментарий :

Accept-Ranges: bytes
ETag: W/"243174107-1583744547157"
Last-Modified: Mon, 09 Mar 2020 09:02:27 GMT
Content-Range: bytes 32243658-243174106/243174107
Content-Type: application/zip
Content-Length: 210930449

В запросе указана начальная позиция 32,243,658 и загружены оставшиеся 210,930,449 байты, заканчивающиеся на файл с 243,174,107 байтами.

Ну, нет, в итоге получился файл с не менее 243,204,042 байтов, т.е. 29,935 байтов слишком много, потому что код всегда записывает full buffer, даже если буфер не был прочитан полностью.

Весьма вероятно, что файл намного больше этого, потому что данные поступают по сети в меньших блоках, так что вполне вероятно, что буфер не заполнен 65,536 байтами на многих вызовах read().

read() возвращает значение len по причине. Ваш код должен быть:

writeFile.write(buf, 0, len);

Кроме того, вы должны использовать try-with-resources, и обычно используется встроенный вызов read(), поэтому он не повторяется, например, код должен быть:

int totalLen = 0;
try (RandomAccessFile writeFile = new RandomAccessFile(desc, "rw")) {
    writeFile.seek(position); // should use value from response header here, not requested value
    try (InputStream is = entity.getContent()) {
        byte[] buf = new byte[65536];
        for (int len; (len = is.read(buf)) > 0; ) {
            totalLen += len;
            writeFile.write(buf, 0, len);
        }
    }
}
response.close();
...