Как узнать, не завершен ли загруженный файл с URL-адреса?

Я использую этот отличный фрагмент из Как загрузить и сохранить файл из Интернета с помощью Java? чтобы загрузить файл с URL-адреса:

URL website = new URL("http://www.website.com/information.asp");
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream("information.html");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);

Но вместо Long.MAX_VALUE я предпочитаю ограничивать загрузку 2 МБ из соображений безопасности, поэтому заменил его на

fos.getChannel().transferFrom(rbc, 0, 2097152);

Но теперь мне интересно, как я могу справиться со случаем, когда размер файла больше 2 МБ?

Что я могу сделать, чтобы проверить, поврежден файл или нет?


person Cyril N.    schedule 17.09.2013    source источник
comment
контрольная сумма — один из лучших способов проверить целостность файла.   -  person Juned Ahsan    schedule 17.09.2013
comment
Но это предполагает, что у меня есть исходная контрольная сумма загруженного файла или что я должен полностью загрузить его раньше, верно?   -  person Cyril N.    schedule 17.09.2013
comment
Да, вам нужна оригинальная контрольная сумма для проверки.   -  person Juned Ahsan    schedule 17.09.2013


Ответы (2)


Рассматривали ли вы возможность проверки заголовка Content-Length в соответствии с RFC? Затем вы можете проверить, превышает ли это какое-то допустимое значение — в вашем случае 2 МБ — и отклонить дальнейшую обработку. Вы можете сделать это с помощью начального HTTP-запроса HEAD, а затем GET, если вы довольны, или путем чтения заголовков только ответа GET и продолжения потоковой передачи, если это приемлемо.

В качестве альтернативы (но, по общему признанию, уродливой) вы можете использовать BufferedReader, передавая буфер размером 2 МБ и сравнивая его с заголовками.

Что касается коррупции, вам лучше использовать контрольную сумму, как указано в других комментариях. Конечно, это требует, чтобы вы заранее знали контрольную сумму ресурса, и вряд ли вы получите ее из самого HTTP-ответа.

person Alex    schedule 17.09.2013

На самом деле у этого вопроса есть два аспекта:

  • как узнать, скачали ли вы весь файл, и

  • как узнать, повреждено ли то, что вы скачали.

Первое, что нужно отметить, это то, что если вы «обрезаете» передачу файла на 2 МБ, то, если видимый размер передаваемого файла составляет 2 МБ, вы можете быть уверены, что он не будет завершен. (Судя по всему, ваш текущий код даст вам байты после декодирования любой кодировки передачи... что упрощает ситуацию.)

Следующее, что следует отметить, это то, что ответ HTTP часто будет включать заголовок Content-length, который сообщает клиенту, сколько байтов (закодированного при передаче) содержимого следует ожидать в теле ответа. Однако это не скажет вам, действительно ли байты, которые вы фактически получили (после декодирования), верны. (Кроме того, этот заголовок является необязательным... вы не можете полагаться на его наличие.)

Как отмечает @ato, вам лучше проверить Content-length в ответе GET (или HEAD) прежде чем вы действительно попытаетесь прочитать данные.

Тем не менее, единственный верный способ узнать, есть ли у вас полный / неповрежденный файл, — это проверить его по контрольной сумме или (в идеале) крипто-хэшу, который вы получили отдельно от передачи. Не существует стандартного способа получения контрольной суммы или хэша с использованием протокола HTTP.

person Stephen C    schedule 17.09.2013