2010-05-28 4 views
19

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

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

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

ответ

14

Протокол HTTP/1.1 позволяет это, только в самом странном и запутанном виде. Вы должны применить следующие три шага proceedure:

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

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

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

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

Если HTTP/1.1 клиент посылает запрос который включает в себя тело запроса, но , который не включает в себя Ожидать поля запроса-заголовка с ожиданием «100-продолжить» , и если клиент напрямую не связан с сервером HTTP/1.1 , а если клиент se когда соединение закрывается , прежде чем получать какой-либо статус с сервера , клиент ДОЛЖЕН повторить запрос .Если клиент повторяет этот запрос, он может использовать следующие «двоичную экспоненциальную отсрочку передачи» алгоритм , чтобы быть уверенным в получении надежного ответа:

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. Это то, что спецификация говорит обручи ДОЛЖНО сделать. Кто знает, какие браузеры ACTUALLY do в этом случае? Не я. Вам нужно будет запустить несколько тестов.
  2. В спецификации упоминается, что это поведение применяется только «, если клиент напрямую не подключен к серверу происхождения HTTP/1.1». Это кажется действительно причудливым требованием, которое на практике означает, что вам может понадобиться подделка заголовков ответов сервера, чтобы сделать вид, что вы прокси или сервер HTTP/1.0.
  3. Некоторые промежуточные протоколы, такие как fast-cgi, не могут активировать ваш скрипт до тех пор, пока запрос не будет завершен. В этом случае вам действительно нужен настоящий сервер сокетов низкого уровня.
  4. Весь этот процесс грязный и запутанный и может даже не работать. На мой взгляд, вам лучше использовать AJAX. Тем не менее, вы спросили, можно ли это сделать без JS.
+0

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

3

Посмотрите на билет django #10850 - "Impossible to stop a large file upload mid-stream". Не решает проблему, но, по крайней мере, это должно помочь вам это понять.

+0

Насколько я могу судить, они говорят либо о прекращении обработки на стороне сервера, либо о переходе на соединение, и для меня это не подходит, потому что ни одна из них не позволяет сразу перенаправлять. – vartec

+0

Я думаю, что отчет об ошибке, по крайней мере, отвечает на ваш вопрос о том, возможно ли это сделать с помощью чистого HTTP, но, возможно, я просто недостаточно умный :). Является ли Javascript не вариантом, или вы просто пытаетесь избежать его использования, если вам не нужно? – sdolan

+0

Требуется работать с широким спектром мобильных устройств, фактически исключая iPhone, BB и Android, которые получают родные приложения. Таким образом, предполагается, что наличие JS не гарантируется. – vartec

-1
  1. использование PCEL расширение uploadprogress, если вы используете Apache
  2. создать файл для опроса мета через Ajax, и вернуть trueor ложь в зависимости от вашего состояния, вы можете также получить файл temp_name и проверьте 1Kb мета ,
  3. вызов ajax необходимо связать с функцией, которая использует заголовки метаобновления HTML для перенаправления или останова до завершения загрузки.


Оформить заказ примеров uploadprogress.

Смежные вопросы