2009-04-08 7 views
101

En WebForms, je devrais normalement avoir le code comme celui-ci pour que le navigateur présente une fenêtre « Télécharger le fichier » avec un type de fichier arbitraire, comme un PDF, et un nom de fichier:Comment puis-je présenter un fichier à télécharger à partir d'un contrôleur 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() 

Comment puis-je obtenir le même tâche dans ASP.NET MVC?

Répondre

163

Renvoyez un FileResult ou FileStreamResult de votre action, selon que le fichier existe ou que vous le créez à la volée.

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

Ceci est un excellent exemple de pourquoi ASP.NET MVC génial. Ce que vous deviez auparavant faire dans 9 lignes de code à la recherche de confusion peut être fait en une ligne. Tellement plus facile! –

+0

Merci tvanfosson, j'ai cherché la meilleure solution pour ce faire, et c'est génial. –

+0

Cela nécessite une extension de fichier sur le nom de fichier ou sinon il ignorera complètement le nom de fichier et contenttype et essaiera juste de diffuser le fichier dans le navigateur. Il utilisera également le nom de la page Web si le navigateur ne reconnaît pas le type de contenu (c'est-à-dire octet-stream) lorsqu'il force le téléchargement et qu'il n'aura pas d'extension du tout. – EdenMachine

4

Vous devriez regarder la méthode File du Controller. C'est exactement pour ça. Il renvoie un FilePathResult au lieu d'un ActionResult.

-3

Utilisez le type de fichier .ashx et utiliser le même code

3

mgnoonan,

Vous pouvez le faire pour retourner 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

Pour forcer le téléchargement d'un fichier PDF fichier, au lieu d'être géré par le plugin PDF du navigateur:

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

Si vous souhaitez laisser le navigateur gérer son comportement par défaut (plugin ou téléchargement), envoyez simplement deux paramètres.

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

Vous devrez utiliser le troisième paramètre pour spécifier un nom pour le fichier dans la boîte de dialogue du navigateur. MISE À JOUR: Charlino a raison, en passant le troisième paramètre (téléchargement du nom de fichier) Content-Disposition: attachment; est ajouté à l'en-tête de réponse HTTP. Ma solution était d'envoyer application\force-download comme le type mime, mais cela génère un problème avec le nom de fichier du téléchargement de sorte que le troisième paramètre est nécessaire pour envoyer un bon nom de fichier, éliminant ainsi la nécessité de forcer un téléchargement.

+6

Techniquement, ce n'est pas ce qui se passe.Techniquement, lorsque vous ajoutez le troisième paramètre, le framework MVC ajoute l'en-tête 'content-disposition: attachment; filename = MyRenamedFile.pdf' - c'est ce qui force le téléchargement. Je vous suggère de remettre le type MIME à 'application/pdf'. – Charlino

+2

Merci Charlino, je n'avais pas réalisé que le troisième paramètre faisait ça, je pensais que c'était juste pour changer le nom du fichier. – guzart

+2

+1 pour mettre à jour votre réponse et expliquer le troisième paramètre + relation «Content-Disposition: attachment; – Charlino

6

Vous pouvez faire la même chose dans Razor ou dans le contrôleur, comme si ..

@{ 
    //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"); 
} 

Ou dans le contrôleur ..

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

    return View(); 
} 

J'ai essayé dans Chrome et IE9, les deux est télécharger le fichier pdf.

Je devrais probablement ajouter que j'utilise RazorPDF pour générer mes fichiers PDF. Voici un blog à ce sujet: http://nyveldt.com/blog/post/Introducing-RazorPDF

Questions connexes