2010-05-28 13 views
19

Ho un modulo con upload di file. I file da caricare in realtà sono immagini e video, quindi possono essere abbastanza grandi. Ho una logica basata sulle intestazioni e il primo 1KB può determinare se il resto verrà elaborato o immediatamente respinto. Nel caso successivo mi piacerebbe reindirizzare il cliente alla pagina di errore senza dover attendere il completamento del caricamento.Il reindirizzamento prima del caricamento POST è stato completato

Il caso è che l'invio della risposta prima del completamento del POST non sembra funzionare. Il reindirizzamento viene ignorato e se si chiude la connessione, il browser si lamenta con "Connessione ripristinata dal peer" Errore.

Quindi la domanda è: è anche possibile farlo in puro HTTP (senza JavaScript sul lato client), e se sì, come?

risposta

14

Il protocollo HTTP/1.1 consente questo, solo in un modo davvero bizzarro e incasinato. È necessario applicare il seguente 3 step proceedure:

  1. immediatamente (bruscamente) chiudere la connessione, memorizzare una bandiera sul lato server per la sessione del client
  2. Utilizzare il flag di rilevare un tentativo di inviare nuovamente gli stessi dati modulo , la specifica raccomanda al cliente di farlo automaticamente
  3. Inviare una stato di errore con un redirect (come 302 temporaneamente spostata)

questo dOVREBBE lavoro perché, come indicato di seguito il cliente è prevista per ritentare un connec almeno una volta dopo essere stati interrotti inaspettatamente. Al tentativo di riprovare si prevede di inviare solo le intestazioni, quindi attendere e osservare una risposta di errore e interrompere l'invio del corpo se ne ottiene uno.

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

8.2.4 Comportamento client Se server chiude prematuramente Connection

Se un HTTP/1.1 client invia una richiesta che comprende un corpo di richiesta, ma che non includono una Aspettatevi campo intestazione richiesta con l'attesa "100-continue" e se il client non è collegato direttamente a un server di origine HTTP/1.1 e se il client la connessione si chiude prima di ricevere qualsiasi stato dal server , il client DOVREBBE ritentare la richiesta .Se il cliente fa ripetere questa richiesta , può utilizzare la seguente "backoff esponenziale binario" algoritmo per essere certi di ottenere un affidabile risposta:

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. 

Se in qualsiasi momento uno stato di errore è ricevuto, il cliente

- SHOULD NOT continue and 

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

trucchi:

  1. Questo è quello che dice la specifica browswers DOVREBBE fare. Chissà quali browser ACTUALLY do in questo caso? Non me. Avrai bisogno di eseguire alcuni test.
  2. La specifica specifica che questo comportamento si applica solo "se il client non è direttamente connesso a un server di origine HTTP/1.1". Sembra un requisito davvero bizzarro, che in pratica significa che potrebbe essere necessario falsificare le intestazioni delle risposte del server per fingere di essere un proxy o un server HTTP/1.0.
  3. Alcuni protocolli intermediari come fast-cgi potrebbero non attivare lo script fino al completamento della richiesta. In questo caso avrai effettivamente bisogno di un vero server socket di basso livello.
  4. Questo intero processo è confuso e complicato e potrebbe anche non funzionare. Faresti meglio a usare AJAX secondo me. Eppure, hai chiesto se poteva essere fatto senza JS.
+0

Devo dire che questa risposta è molto utile. Ciononostante, dubito che cercherò persino di implementarlo, poiché il servizio che ho è generalmente privo di status e dietro un bilanciamento del carico non appiccicoso. – vartec

3

Dai un'occhiata al biglietto django #10850 - "Impossible to stop a large file upload mid-stream". Non risolve il problema, ma almeno dovrebbe aiutarti a capirlo.

+0

Per quanto posso vedere, stanno parlando di interrompere l'elaborazione sul lato server o di resettare la connessione, né è una buona opzione per me, perché nessuno dei due consente il reindirizzamento immediato. – vartec

+0

Penso che la segnalazione di bug almeno risponda alla tua domanda se sia o meno possibile farlo con HTTP puro, ma forse non sono abbastanza intelligente :). Javascript non è un'opzione, o stai solo cercando di evitare di usarlo se non devi? – sdolan

+0

È necessario lavorare su un'ampia gamma di dispositivi mobili, in realtà escludendo iPhone, BB e Android, che ottengono app native. Quindi l'ipotesi è che avere JS non è garantito. – vartec

-1
  1. uso PCEL uploadprogress estensione se si utilizza Apache
  2. creare un file di sondaggio meta tramite Ajax, e tornare trueor falso, sulla base di condizioni, si potrebbe anche ottenere il file temp_name e verificare la meta 1kb .
  3. la chiamata ajax deve essere associata a una funzione che utilizza intestazioni di meta-aggiornamento HTML per reindirizzare o rimanere fino al termine dei caricamenti.


Verificare gli esempi di uploadstog.