2009-04-08 7 views
101

In WebForms, io normalmente si sarebbero codice come questo per permettere al browser presentare una "Download file" popup con un tipo di file arbitrario, come un PDF, e un nome di file:Come posso presentare un file per il download da un controller MVC?

Response.Clear() 
Response.ClearHeaders() 
''# Send the file to the output stream 
Response.Buffer = True 

Response.AddHeader("Content-Length", pdfData.Length.ToString()) 
Response.AddHeader("Content-Disposition", "attachment; filename= " & Server.HtmlEncode(filename)) 

''# Set the output stream to the correct content type (PDF). 
Response.ContentType = "application/pdf" 

''# Output the file 
Response.BinaryWrite(pdfData) 

''# Flushing the Response to display the serialized data 
''# to the client browser. 
Response.Flush() 
Response.End() 

Come faccio a ottenere lo stesso attività in ASP.NET MVC?

risposta

163

Restituisci un FileResult o FileStreamResult dall'azione, a seconda che il file esista o lo crei al volo.

public ActionResult GetPdf(string filename) 
{ 
    return File(filename, "application/pdf", Server.UrlEncode(filename)); 
} 
+10

Questo è un grande esempio del perché ASP.NET MVC impressionante. Quello che prima dovevi fare in 9 righe di codice dall'aspetto confuso può essere fatto in una riga. Molto più facile! –

+0

Grazie a tvanfosson, ho cercato la soluzione migliore per farlo, e questo è fantastico. –

+0

Ciò richiede un'estensione di file sul nome del file o altrimenti ignorerà completamente il nome file e il tipo di contenuto e semplicemente cercherà di inviare il file al browser. Inoltre, utilizzerà il nome della pagina Web solo se il browser non riconosce il tipo di contenuto (ovvero octet-stream) quando impone il download e non avrà un'estensione. – EdenMachine

4

Si dovrebbe guardare il metodo File del controller. Questo è esattamente ciò che è per. Restituisce un FilePathResult invece di un ActionResult.

-3

tipo di file Usa Ashx e utilizzare lo stesso codice

3

mgnoonan,

È possibile farlo per restituire un FileStream:

/// <summary> 
/// Creates a new Excel spreadsheet based on a template using the NPOI library. 
/// The template is changed in memory and a copy of it is sent to 
/// the user computer through a file stream. 
/// </summary> 
/// <returns>Excel report</returns> 
[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult NPOICreate() 
{ 
    try 
    { 
     // Opening the Excel template... 
     FileStream fs = 
      new FileStream(Server.MapPath(@"\Content\NPOITemplate.xls"), FileMode.Open, FileAccess.Read); 

     // Getting the complete workbook... 
     HSSFWorkbook templateWorkbook = new HSSFWorkbook(fs, true); 

     // Getting the worksheet by its name... 
     HSSFSheet sheet = templateWorkbook.GetSheet("Sheet1"); 

     // Getting the row... 0 is the first row. 
     HSSFRow dataRow = sheet.GetRow(4); 

     // Setting the value 77 at row 5 column 1 
     dataRow.GetCell(0).SetCellValue(77); 

     // Forcing formula recalculation... 
     sheet.ForceFormulaRecalculation = true; 

     MemoryStream ms = new MemoryStream(); 

     // Writing the workbook content to the FileStream... 
     templateWorkbook.Write(ms); 

     TempData["Message"] = "Excel report created successfully!"; 

     // Sending the server processed data back to the user computer... 
     return File(ms.ToArray(), "application/vnd.ms-excel", "NPOINewFile.xls"); 
    } 
    catch(Exception ex) 
    { 
     TempData["Message"] = "Oops! Something went wrong."; 

     return RedirectToAction("NPOI"); 
    } 
} 
57

per forzare il download di un PDF presentare, invece di essere gestito dal plug-in PDF del browser:

public ActionResult DownloadPDF() 
{ 
    return File("~/Content/MyFile.pdf", "application/pdf", "MyRenamedFile.pdf"); 
} 

Se si desidera consentire al browser di gestire il comportamento predefinito (plug-in o download), è sufficiente inviare due parametri.

public ActionResult DownloadPDF() 
{ 
    return File("~/Content/MyFile.pdf", "application/pdf"); 
} 

È necessario utilizzare il terzo parametro per specificare un nome per il file nella finestra di dialogo del browser.

UPDATE: Charlino ha ragione, quando si passa il terzo parametro (download filename) Content-Disposition: attachment; viene aggiunto all'Http Response Header. La mia soluzione era di inviare application\force-download come il mime-type, ma questo genera un problema con il nome del file del download in modo che il terzo parametro è tenuto ad inviare un buon nome di file, eliminando quindi la necessità di forza un download.

+6

Tecnicamente non è quello che sta succedendo.Tecnicamente quando aggiungi il terzo parametro, il framework MVC aggiunge l'intestazione 'content-disposition: attachment; filename = MyRenamedFile.pdf' - questo è ciò che forza il download. Suggerirei di riportare il tipo MIME a 'application/pdf'. – Charlino

+2

Grazie Charlino, non mi ero reso conto che il terzo parametro lo stava facendo, pensavo che fosse solo per cambiare il nome del file. – guzart

+2

+1 per l'aggiornamento della risposta e la spiegazione del terzo parametro + relazione 'Content-Disposition: attachment;'. – Charlino

6

Si può fare lo stesso in rasoio o nel controller, in questo modo ..

@{ 
    //do this on the top most of your View, immediately after `using` statement 
    Response.ContentType = "application/pdf"; 
    Response.AddHeader("Content-Disposition", "attachment; filename=receipt.pdf"); 
} 

O nel controller ..

public ActionResult Receipt() { 
    Response.ContentType = "application/pdf"; 
    Response.AddHeader("Content-Disposition", "attachment; filename=receipt.pdf"); 

    return View(); 
} 

Ho provato questo in Chrome e IE9, entrambi è scaricando il file pdf.

Probabilmente dovrei aggiungere che sto usando RazorPDF per generare i miei file PDF. Ecco un blog su di esso: http://nyveldt.com/blog/post/Introducing-RazorPDF

Problemi correlati