2010-05-28 41 views
19

Tengo un formulario con carga de archivos. Los archivos que se cargarán en realidad son imágenes y videos, por lo que pueden ser bastante grandes. Tengo una lógica que basada en los encabezados y los primeros 1 KB puede determinar si el resto será procesado o rechazado de inmediato. En el caso posterior, me gustaría redirigir al cliente a la página de error sin tener que esperar a que termine la carga.Redirigir antes de que se haya completado la carga POST

El caso es que el simple hecho de enviar una respuesta antes de que se complete el POST no parece funcionar. La redirección se ignora y si cierro la conexión, el navegador se queja con "Restablecimiento de conexión por pares" error.

Entonces la pregunta es: ¿es posible hacerlo en HTTP puro (sin JavaScript en el lado del cliente) y, de ser así, cómo?

Respuesta

14

El protocolo HTTP/1.1 permite esto, simplemente de una manera realmente extraña y desordenada. Es necesario aplicar los siguientes 3 pasos proceedure:

  1. Inmediatamente (bruscamente) cerrar la conexión, almacenar una bandera de servidor para la sesión del cliente
  2. Utilice el indicador para detectar un intento de volver a enviar los mismos datos de forma , la especificación recomienda que el cliente haga esto automáticamente
  3. Envía un estado de error con una redirección (como 302 Movido temporalmente)

este DEBE trabajo porque, como se indica a continuación el cliente se espera que vuelva a intentar un connec al menos una vez después de ser cortado inesperadamente. En el (los) intento (s) de reintento se espera que solo envíe los encabezados, luego espere y observe si hay una respuesta de error y aborte enviando el cuerpo si recibe uno.

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

8.2.4 Comportamiento del cliente si el servidor cierra la conexión antes de tiempo

Si un cliente HTTP/1.1 envía una solicitud que incluye un cuerpo de la petición, pero que no incluye un Expect campo de encabezado de solicitud con la expectativa "100-continue" , y si el cliente no está conectado directamente a un servidor de origen HTTP/1.1 , y si el cliente se es la conexión cerrar antes de recibir cualquier estado del servidor , el cliente DEBE volver a intentar la solicitud .Si el cliente vuelva a intentar esta solicitud , se pueden utilizar los siguientes "binario retroceso exponencial" algoritmo tener la seguridad de obtener una fiable respuesta:

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. 

Si en algún momento un estado de error se recibido, el cliente

- SHOULD NOT continue and 

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

Gotchas:

  1. Eso es lo que dice la especificación browswers SHOULD do. ¿Quién sabe qué navegadores ACTUALMENTE hacer en este caso? Yo no. Tendrás que ejecutar algunas pruebas.
  2. La especificación menciona específicamente que este comportamiento solo aplica "si el cliente no está conectado directamente a un servidor de origen HTTP/1.1". Parece un requisito realmente extraño que en la práctica significa que puede necesitar falsificar los encabezados de respuesta de su servidor para simular que es un servidor proxy o HTTP/1.0.
  3. Ciertos protocolos intermediarios como fast-cgi pueden no activar su script hasta que se complete la solicitud. En este caso, realmente necesitará un servidor de socket real de bajo nivel.
  4. Todo este proceso es desordenado y complicado y puede que ni siquiera funcione. Sería mejor usar AJAX en mi opinión. Aún así, preguntaste si podría hacerse sin JS.
+0

Debo decir que esta respuesta es bastante útil. Sin embargo, dudo que incluso intente implementarlo, ya que el servicio que tengo generalmente es sin estado y está detrás del equilibrador de carga no adhesivo. – vartec

3

Eche un vistazo al boleto django #10850 - "Impossible to stop a large file upload mid-stream". No resuelve el problema, pero al menos debería ayudarte a entenderlo.

+0

Por lo que puedo ver, están hablando de detener el procesamiento en el lado del servidor o restablecer la conexión, tampoco es una buena opción para mí, porque ninguno permite la redirección inmediata. – vartec

+0

Creo que el informe de errores al menos responde a su pregunta de si es posible o no hacerlo con HTTP puro, pero tal vez no soy lo suficientemente inteligente :). ¿JavaScript no es una opción, o simplemente está tratando de evitar usarlo si no es necesario? – sdolan

+0

Se requiere para trabajar en una amplia gama de dispositivos móviles, excluyendo realmente iPhone, BB y Android, que obtienen aplicaciones nativas. Entonces, la suposición es que tener JS no está garantizado. – vartec

-1
  1. uso PCEL uploadprogress extensión si se utiliza Apache
  2. crear un archivo para sondear meta a través de Ajax, y volver trueor falsa sobre la base de su condición, también se puede obtener el archivo temp_name y comprobar la meta de 1 kb .
  3. la llamada ajax debe vincularse con una función que utiliza encabezados meta-refresh HTML para redirigir o permanecer hasta que se realicen las cargas.


Verifique los ejemplos de la carga progresiva.

Cuestiones relacionadas