posts - 315, comments - 268, trackbacks - 15

My Links

News

View Pietro Libro's profile on LinkedIn

DomusDotNet
   DomusDotNet

Pietro Libro

Tag Cloud

Article Categories

Archives

Post Categories

Blogs amici

Links

Content-disposition, ContentType e PDF

Supponiamo di avere un'applicazione web (classica gestione dei preventivi web, ad esempio), che al termine di una serie di operazioni produce un file pdf (il preventivo). Se volessimo rendere scaricabile/apribile il file senza che l'utente debba nuovamente fare click su di un collegamento, al termine delle operazioni potremmo eseguire il redirect verso una pagina contenente del tipo:

1 protected void Page_SaveStateComplete(object sender, EventArgs e) 2 { 3 try 4 { 5 RenderDocument(this.Context); 6 } 7 catch { } 8 } 9 10 public void RenderDocument(System.Web.HttpContext context) 11 { 12 try 13 { 14 string basePath = context.Request.MapPath("."); 15 string partialPath = @"PDF\Documento_convegno.pdf"; 16 string fullPath = System.IO.Path.Combine(basePath, partialPath); 17 //Pulisce il response, per non trasmettere byte che non c'entrano nulla... 18 context.Response.Clear(); 19 //Imposta il tipo di contenuto 20 context.Response.ContentType = "application/pdf"; 21 //Aggiunge l'HTTP header necessario 22 context.Response.AddHeader("Content-disposition", "attachment; filename=Documento_convegno.pdf"); 23 //Invio del file 24 context.Response.TransmitFile(fullPath); 25 context.Response.Flush (); 26 } 27 catch { } 28 }

Nell'esempio il tipo di documento è fissato, ma potremmo utilizzare altri tipi secondo dell'estensione del file, application/rtf per i file rtf e application/msword per i file di Microsoft Word. Invece di utilizzare una pagina aspx,  come suggerito da Andrea Colaci è possibile utilizzare un Generic Handler (file con estensione .ashx). In questo caso il codice potrebbe essere:

1 <%@ WebHandler Language="C#" Class="RendereHandler" %> 2 3 using System; 4 using System.Web; 5 6 public class RendereHandler : IHttpHandler 7 { 8 9 public void ProcessRequest(HttpContext context) 10 { 11 RenderDocument(context); 12 } 13 14 public bool IsReusable 15 { 16 get 17 { 18 return false; 19 } 20 } 21 22 public void RenderDocument(System.Web.HttpContext context) 23 { 24 try 25 { 26 string basePath = context.Request.MapPath("."); 27 string partialPath = @"PDF\Documento_convegno.pdf"; 28 string fullPath = System.IO.Path.Combine(basePath, partialPath); 29 //Pulisce il response, per non trasmettere byte che non c'entrano nulla... 30 context.Response.Clear(); 31 //Imposta il tipo di contenuto 32 context.Response.ContentType = "application/pdf"; 33 //Aggiunge l'HTTP header necessario 34 context.Response.AddHeader("Content-disposition", "attachment; filename=Documento_convegno.pdf"); 35 //Invio del file 36 context.Response.TransmitFile(fullPath); 37 context.Response.Flush(); 38 } 39 catch { } 40 } 41 }

In ambo i casi, la trasmissione del file avviene per mezzo del metodo Response.TransmitFile, invece di leggere con un ciclo il contenuto del file (come suggerito da Fabrizio) Questo metodo permette di scrivere direttamente su HTTP response senza prima creare un buffer in memoria. HttpResponse.TransmitFile

Secondo dei casi è possibile impostare correttamente la proprietà IHttpHandler.IsReusable

Print | posted on martedì 13 maggio 2008 17:04 | Filed Under [ C# ]

Feedback

Gravatar

# re: Content-disposition, ContentType e PDF

Grazie del suggerimento, ho modificato il post, aggiungendo il tuo suggerimento. In queto caso non vi erano particolari configurazioni del web.config o di ISS, anche se non è sempre vero
14/05/2008 01:05 | Pietro Libro
Gravatar

# re: Content-disposition, ContentType e PDF

Ciao fabrizio,

ho utilizzato Response.Flush e non Response.End proprio perchè l'applicazione gira su IIS7, e su ques'ultimo viene sollevata un eccezione, gestita, ma pur sempre un eccezione. Quindi ho preferito utilizzare Flush. Per quanto concerne la dimensione del PDF, nel mio caso si tratta di file di piccole dimensioni, ma per la serie "non si può mai sapere", ho modificato il codice seguendo il tuo suggerimento. Grazie.
14/05/2008 14:36 | Pietro Libro
Gravatar

# re: Content-disposition, ContentType e PDF

Ancora un paio di cose.

A me questo su IIS7 su Win2008RC0 funziona:

protected void Page_Load(object sender, EventArgs e)
{
string fileName = "3mb.pdf";
string storeFileNameFP = "3mb.pdf";
Response.Clear();
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName);
Response.TransmitFile(storeFileNameFP);
Response.End();
}

Vedo che tu fai la trasmissione del file in Page_SaveStateComplete. Io invece lavoro in Page_Load. Prova a lavorare in Page_Load e vedi se hai ancora problemi.

Tra l'altro... stavo pensando... forse è una fesseria ma in un ashx file non ha senso usare Response.End e Response.Flush. Io proverei a toglierele entrambe.
14/05/2008 16:07 | fabrizio
Gravatar

# re: Content-disposition, ContentType e PDF

Per quanto riguarda l'errore è "Thread Abortito". Potrebbe essere un problema di configurazione di IIS...
15/05/2008 01:03 | Pietro Libro
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET