La nostra applicazione Web (Web Form ASP.NET) ha una pagina che visualizza un file PDF generato di recente per gli utenti. Poiché il file PDF è talvolta abbastanza grande, abbiamo implementato un approccio "streaming" per inviarlo al browser client in blocchi.Perché ASP.NET sostituisce un'intestazione Content-Length con un'intestazione Transfer-Encoding quando si svuota manualmente una risposta?
Nonostante l'invio dei dati in blocchi, conosciamo l'intera dimensione del file prima di inviarlo, quindi impostiamo l'intestazione Content-Length in modo appropriato. Questo ha funzionato nel nostro ambiente di produzione per un po '(e continua a funzionare nel nostro ambiente di test con una configurazione praticamente identica) fino ad oggi. Il problema segnalato era che Chrome avrebbe tentato di aprire il file PDF ma si sarebbe bloccato con l'animazione "Caricamento" bloccata.
Poiché tutto funzionava ancora bene nel nostro ambiente di test, ero in grado di usare Firebug per dare un'occhiata alle intestazioni di risposta che tornavano in entrambi gli ambienti. Nell'ambiente di test, stavo vedendo un'intestazione appropriata "Content-Length", mentre in produzione era stata sostituita con una codifica di trasferimento : chunked. A Chrome non piace questo, quindi il riagganciarsi.
Ho letto alcuni articoli e post che parlano di come può essere visualizzata l'intestazione Transfer-Encoding quando non viene fornita l'intestazione Content-Length, ma stiamo specificando l'intestazione Content-Length e tutto sembra funzionare correttamente durante l'esecuzione del stesso codice per lo stesso file PDF su un server di prova.
Sia i server di test che di produzione eseguono IIS 7.5 ed entrambi hanno la compressione dinamica e statica abilitata.
Ecco il codice in questione:
var fileInfo = new FileInfo(fileToSendDown);
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "filename=test.pdf");
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
var buffer = new byte[1024];
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
int read;
while ((read = fs.Read(buffer, 0, 1024)) > 0)
{
if (!response.IsClientConnected) break;
Response.OutputStream.Write(buffer, 0, read);
Response.Flush();
}
}
ho avuto la fortuna di vedere lo stesso comportamento sulla mia workstation locale in modo da utilizzare il debugger ho potuto vedere che il 'Transfer-Encoding: chunked' intestazione è impostato sul 2 ° passaggio del ciclo while durante la chiamata a "Flush". A quel punto, la risposta ha sia un'intestazione Content-Length che un'intestazione Transfer-Encoding, ma in qualche modo quando la risposta raggiunge il browser Firebug mostra solo l'intestazione Transfer-Encoding.
UPDATE
Penso di aver rintracciato questo fino a utilizzando una combinazione di invio dei dati verso il basso in "blocchi" e allegando un 'filtro' per l'oggetto HttpResponse (stavamo usando un filtro per tenere traccia la dimensione di viewstate inviata a ogni pagina). Non ha senso usare noi un filtro HTTP quando si invia un PDF al browser, quindi cancellare il filtro qui ha risolto il nostro problema. Ho deciso di scavare un po 'più a fondo per pura curiosità e ho aggiornato questa domanda se qualcun altro dovesse mai imbattersi in questo problema in futuro.
Ho una semplice app su AppHarbor che riproduce il problema: http://transferencodingtest.apphb.com/. Se controlli sia "Usa filtro?" e "Send In Chunks?" i riquadri dovrebbero essere in grado di visualizzare l'intestazione 'transfer-encoding: chunked' (utilizzando gli strumenti di sviluppo di Chrome, Firebug, Fiddler, qualsiasi altra cosa). Se una delle caselle non è selezionata, otterrai un'intestazione corretta per la lunghezza del contenuto. Il codice sottostante è su GitHub modo da poter vedere cosa sta succedendo dietro le quinte:
https://github.com/appakz/TransferEncodingTest
Si noti che a Repro localmente avresti bisogno di configurare un sito web locale in IIS 7.5 (7 può anche funzionare, Non ho provato). Il server di sviluppo ASP .NET fornito con Visual Studio NON restituisce il problema.
ho aggiunto qualche dettaglio in più di un post sul blog qui: 'Content-Length' Header Replaced With 'Transfer-Encoding: Chunked' in ASP .NET
So che questa è una vecchia domanda, ma facendo ricerche simili mi sono imbattuto in [questo eccellente post] (http://geekswithblogs.net/GruffCode/archive/2012/01/02/lsquocontent-lengthrsquo-header-replaced-with-lsquotransfer-encoding-chunkedrsquo-in-asp- .net.aspx) spiegando questo stesso problema. Ci vuole una serie specifica di circostanze per creare questo problema. Spero che questo aiuti un futuro lettore. – user158017
Questo è il post che ho scritto dopo aver fatto la domanda, non ricevendo una risposta, e infine ho trovato alcuni passaggi per riprodurlo in modo coerente. Ho aggiornato la domanda originale con i link all'app di esempio che la riproduce, ma suppongo che dovrei aggiungere anche un link al post del blog. –