Размер загружаемого файла - PullRequest
12 голосов
/ 11 ноября 2008

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

Ответы [ 3 ]

12 голосов
/ 11 ноября 2008

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

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

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

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

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

2 голосов
/ 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 в заголовке файловой части (каждый файл имеет свой собственный заголовок, который является целью многочастного кодирования). Помните, что браузер обязан установить соответствующий тип контента, угадав тип файла; Вы не можете гарантировать это, но он должен быть достаточно надежным для досрочного отклонения (однако лучше проверить весь файл, когда он полностью доступен).

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

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

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

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

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

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

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

...