Перенаправление до завершения загрузки POST - PullRequest
20 голосов
/ 28 мая 2010

У меня есть форма с загрузкой файлов. Файлы для загрузки на самом деле представляют собой картинки и видео, поэтому они могут быть довольно большими. У меня есть логика, которая на основе заголовков и первых 1 КБ может определить, будут ли остальные обработаны или немедленно отклонены. В последнем случае я бы хотел перенаправить клиента на страницу ошибки, не дожидаясь окончания загрузки.

Дело в том, что просто отправка ответа до завершения POST, похоже, не работает. Перенаправление игнорируется, и если я закрываю соединение, браузер выдает ошибку «Сброс соединения по пиру» .

Итак, вопрос в том: возможно ли это сделать в чистом HTTP (без JavaScript на стороне клиента), и если да, то как?

Ответы [ 3 ]

15 голосов
/ 03 июня 2010

Протокол HTTP / 1.1 допускает это, просто очень странным и запутанным способом. Вам необходимо применить следующие 3 шага:

  1. Немедленно (внезапно) закрыть соединение, сохранить флаг на стороне сервера для сеанса клиента
  2. Используйте флаг, чтобы обнаружить попытку повторно отправить те же данные формы, спецификация рекомендует клиенту сделать это автоматически
  3. Отправить сообщение об ошибке с перенаправлением (например, 302 временно перемещен)

Это ДОЛЖНО работать, поскольку, как показано ниже, клиент, как ожидается, попытается повторить соединение хотя бы один раз после неожиданного отключения. При повторной попытке (попытках) ожидается только отправка заголовков, затем ожидание и ожидание ответа об ошибке и прекращение отправки тела, если оно получено.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html

8.2.4 Поведение клиента, если сервер преждевременно закрывает соединение

Если клиент HTTP / 1.1 отправляет запрос который включает в себя тело запроса, но который не включает в себя ожидание поле заголовка запроса с Ожидание "100-продолжить", и если клиент не связан напрямую с Сервер происхождения HTTP / 1.1, и если клиент видит соединение закрытым до получения какого-либо статуса от сервер, клиент должен повторить попытку запрос. Если клиент повторить это запрос МОЖЕТ использовать следующее алгоритм "двоичного экспоненциального отката" быть уверенным в получении надежного Ответ:

  1. Initiate a new connection to the server

  2. Transmit the request-headers

  3. Initialize a variable R to the estimated round-trip time to the
     server (e.g., based on the time it took to establish the
     connection), or to a constant value of 5 seconds if the round-
     trip time is not available.

  4. Compute T = R * (2**N), where N is the number of previous
     retries of this request.

  5. Wait either for an error response from the server, or for T
     seconds (whichever comes first)

  6. If no error response is received, after T seconds transmit the
     body of the request.

  7. If client sees that the connection is closed prematurely,
     repeat from step 1 until the request is accepted, an error
     response is received, or the user becomes impatient and
     terminates the retry process.

Если в любой момент состояние ошибки получил, клиент

  - SHOULD NOT continue and

  - SHOULD close the connection if it has not completed sending the
    request message.

Gotchas:

  1. Это то, что спецификация говорит браузерам СЛЕДУЕТ делать. Кто знает, что делают браузеры АКТУАЛЬНО в этом случае? Не я. Вам нужно будет выполнить несколько тестов.
  2. В спецификации особо упоминается, что это поведение применимо только к , если клиент не подключен напрямую к серверу происхождения HTTP / 1.1 . Это кажется действительно странным требованием, которое на практике означает, что вам, возможно, придется подделывать заголовки ответа вашего сервера, чтобы представить себя прокси-сервером или сервером HTTP / 1.0.
  3. Некоторые промежуточные протоколы, такие как fast-cgi, могут не активировать ваш скрипт, пока запрос не будет выполнен. В этом случае вам действительно понадобится настоящий низкоуровневый сервер сокетов.
  4. Весь этот процесс запутанный и запутанный и может даже не работать. Тебе было бы лучше использовать AJAX по моему мнению. Тем не менее, вы спросили, можно ли это сделать без JS.
3 голосов
/ 29 мая 2010

Посмотрите на билет django # 10850 - «Невозможно остановить загрузку большого файла в середине потока» . Не решает проблему, но, по крайней мере, она должна помочь вам понять это.

0 голосов
/ 08 июня 2010
  1. используйте расширение PCEL uploadprogress, если вы используете apache
  2. создайте файл для опроса мета через Ajax и верните true или false в зависимости от вашего состояния, вы также можете получить файл temp_name и проверить мета 1 КБ.
  3. вызов ajax должен быть связан с функцией, которая использует заголовки метаобновления HTML для перенаправления или остается до завершения загрузки.


Ознакомьтесь с примерами загрузки.

...