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