Ich habe ein Problem beim Senden von in einer Datenbank gespeicherten Dateien an den Benutzer in ASP.NET MVC. Ich möchte eine Ansicht mit zwei Links, von denen einer die Datei anzeigt und der an den Browser gesendete Mimetyp bestimmt, wie damit umgegangen werden soll, und der andere, um einen Download zu erzwingen.
Wenn ich eine aufgerufene Datei anzeigen möchte SomeRandomFile.bak
und dem Browser kein Programm zum Öffnen von Dateien dieses Typs zugeordnet ist, kann ich problemlos das Download-Verhalten verwenden. Wenn ich jedoch eine aufgerufene Datei anzeigen möchte SomeRandomFile.pdf
oder SomeRandomFile.jpg
die Datei einfach öffnen möchte. Ich möchte aber auch einen Download-Link zur Seite halten, damit ich unabhängig vom Dateityp eine Download-Eingabeaufforderung erzwingen kann. Macht das Sinn?
Ich habe es versucht FileStreamResult
und es funktioniert für die meisten Dateien. Der Konstruktor akzeptiert standardmäßig keinen Dateinamen. Daher wird unbekannten Dateien ein Dateiname zugewiesen, der auf der URL basiert (die die zu erweiternde Erweiterung basierend auf dem Inhaltstyp nicht kennt). Wenn ich den Dateinamen durch Angabe erzwinge, kann der Browser die Datei nicht mehr direkt öffnen, und ich erhalte eine Download-Eingabeaufforderung. Hat das noch jemand erlebt?
Dies sind die Beispiele für das, was ich bisher versucht habe.
//Gives me a download prompt.
return File(document.Data, document.ContentType, document.Name);
//Opens if it is a known extension type, downloads otherwise (download has bogus name and missing extension)
return new FileStreamResult(new MemoryStream(document.Data), document.ContentType);
//Gives me a download prompt (lose the ability to open by default if known type)
return new FileStreamResult(new MemoryStream(document.Data), document.ContentType) {FileDownloadName = document.Name};
Irgendwelche Vorschläge?
UPDATE:
Diese Frage scheint bei vielen Leuten Anklang zu finden, daher dachte ich, ich würde ein Update veröffentlichen. Die Warnung zu der akzeptierten Antwort unten, die Oskar in Bezug auf internationale Zeichen hinzugefügt hat, ist vollständig gültig, und ich habe sie aufgrund der Verwendung der ContentDisposition
Klasse einige Male getroffen . Ich habe seitdem meine Implementierung aktualisiert, um dies zu beheben. Der folgende Code stammt aus meiner letzten Version dieses Problems in einer ASP.NET Core-App (Full Framework). Er sollte jedoch auch in einer älteren MVC-Anwendung mit minimalen Änderungen funktionieren, da ich die System.Net.Http.Headers.ContentDispositionHeaderValue
Klasse verwende.
using System.Net.Http.Headers;
public IActionResult Download()
{
Document document = ... //Obtain document from database context
//"attachment" means always prompt the user to download
//"inline" means let the browser try and handle it
var cd = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = document.FileName
};
Response.Headers.Add(HeaderNames.ContentDisposition, cd.ToString());
return File(document.Data, document.ContentType);
}
// an entity class for the document in my database
public class Document
{
public string FileName { get; set; }
public string ContentType { get; set; }
public byte[] Data { get; set; }
//Other properties left out for brevity
}