Размер загруженного файла

Отправляют ли веб-браузеры размер файла в заголовке http при загрузке файла на сервер? И если это так, то можно ли отказаться от файла, просто прочитав заголовок, а не дожидаясь завершения всего процесса загрузки?


person user36529    schedule 11.11.2008    source источник


Ответы (3)


http://www.faqs.org/rfcs/rfc1867.html

HTTP-клиентам рекомендуется указывать длину содержимого для общего ввода файла, чтобы загруженный сервер мог определить, не являются ли предлагаемые данные файла слишком большими для разумной обработки

Но длина содержимого не требуется, поэтому на нее нельзя полагаться. Кроме того, злоумышленник может подделать неверную длину содержимого.

Прочитать содержимое файла — единственный надежный способ. Сказав это, если длина содержимого присутствует и слишком велика, было бы разумно закрыть соединение.

Кроме того, контент отправляется как составной, поэтому большинство современных фреймворков сначала декодируют его. Это означает, что вы не получите поток байтов файла до тех пор, пока не будет выполнена структура, что может означать «пока весь файл не будет загружен».

person Vladimir Dyuzhev    schedule 11.11.2008

РЕДАКТИРОВАТЬ: прежде чем заходить слишком далеко, вы можете проверить этот другой ответ, полагаясь на конфигурацию apache: Использование jQuery, ограничение размера файла перед загрузкой . приведенное ниже описание полезно только в том случае, если вам действительно нужно еще больше индивидуальных отзывов.

Да, вы можете получить некоторую информацию заранее, прежде чем разрешить загрузку всего файла.

Вот пример заголовка формы с атрибутом enctype="multipart/form-data":

POST / HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.7,fr-be;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------886261531333586100294758961
Content-Length: 135361

-----------------------------886261531333586100294758961
Content-Disposition: form-data; name=""; filename="IMG_1132.jpg"
Content-Type: image/jpeg

(data starts here and ends with -----------------------------886261531333586100294758961 )

У вас есть Content-Length в заголовке, и дополнительно есть Content-Type в заголовке файловой части (каждый файл имеет свой собственный заголовок, что и является целью составного кодирования). Имейте в виду, что ответственность за установку соответствующего Content-Type, угадывая тип файла, лежит на браузере; вы не можете гарантировать это, но это должно быть достаточно надежным для раннего отказа (но вам лучше проверить весь файл, когда он полностью доступен).

Теперь есть загвоздка. Раньше я фильтровал файлы изображений не по размеру, а по типу содержимого; но поскольку вы хотите остановить запрос как можно скорее, возникает та же проблема: браузер получает ваш ответ только после отправки всего запроса, включая содержимое формы и, таким образом, загруженные файлы.

Если вам не нужен предоставленный контент и вы остановили загрузку, у вас нет другого выбора, кроме как жестоко закрыть сокет. Пользователь увидит только сбивающее с толку сообщение «соединение сброшено узлом». И это отстой, но так задумано.

Таким образом, вы хотите использовать этот метод только в случаях фоновых асинхронных проверок (с использованием таймера, который проверяет поле файла). Итак, у меня был этот хак:

  • Я использую jquery, чтобы сообщить мне, изменилось ли поле файла
  • При выборе нового файла отключите все остальные поля файла в той же форме, чтобы получить только этот файл.
  • Отправьте файл асинхронно (jQuery может сделать это за вас, он использует скрытый фрейм)
  • На стороне сервера проверьте заголовок (длина контента, тип контента,...), разорвите соединение, как только получите то, что вам нужно.
  • Установите переменную сеанса, сообщающую, был ли этот файл в порядке или нет.
  • На стороне клиента, поскольку файл загружается во фрейм, вы даже не получаете никакой обратной связи, если соединение закрыто. Единственная альтернатива — таймер.
  • На стороне клиента таймер опрашивает сервер, чтобы получить статус загруженного файла. На стороне сервера у вас есть эта переменная сеанса, отправьте ее обратно в браузер.
  • У клиента есть код состояния; отобразите его в своей форме: сообщение об ошибке, зеленая галочка/красный X, что угодно. Сбросить поле файла или отключить форму, решать вам. Не забудьте снова включить другие поля файла.

Довольно грязно, а? Если у кого-то из вас есть лучшая альтернатива, я весь внимание.

person Community    schedule 11.11.2008

  1. Я не уверен, но не стоит особо доверять чему-либо, отправленному в заголовке, так как это может быть подделано пользователем.

  2. Это зависит от того, как работает сервер. Например, в PHP ваш скрипт не будет работать до тех пор, пока загрузка файла не будет завершена, поэтому это невозможно.

person Tom Haigh    schedule 11.11.2008