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
}
quelle
Inline = true
, stellen Sie sicher, dass Sie NICHT die 3-Parameter-Überladung verwendenFile()
, bei der der Dateiname als 3. Parameter verwendet wird. Es wird im Internet Explorer arbeiten, aber Chrome wird ein Duplikat Kopf berichten und sich weigern , das Bild zu präsentieren.Ich hatte Probleme mit der akzeptierten Antwort, da kein Typ auf die Variable "document" hinwies:
var document = ...
Ich poste also, was für mich als Alternative funktioniert hat, falls jemand anderes Probleme hat.quelle
AppDomain.CurrentDomain.BaseDirectory
istSystem.Web.HttpContext.Current.Server.MapPath("~")
, dass dies auf einem realen Server möglicherweise besser funktioniert als auf einem lokalen Computer.Darin Dimitrovs Antwort ist richtig. Nur eine Ergänzung:
Response.AppendHeader("Content-Disposition", cd.ToString());
Dies kann dazu führen, dass der Browser das Rendern der Datei fehlschlägt, wenn Ihre Antwort bereits einen "Content-Disposition" -Header enthält. In diesem Fall möchten Sie möglicherweise Folgendes verwenden:quelle
pdf
Datei, wenn ich Content-Type gesetzt , wieSystem.Net.Mime.MediaTypeNames.Application.Octet
es herunterladen sogar zwingen werde , wenn ich gesetztInline = true
, aber wenn ich nachResponse.ContentType = MimeMapping.GetMimeMapping(filePath)
, das heißtapplication/pdf
, es kann richtig eher geöffnet als DownloadResponse.Headers.Add
erfordern einen integrierten IIS-Pipeline-Modus. Selbst wenn der App-Pool als integriert festgelegt ist, wird eine Ausnahme ausgelöst. Lösung. Verwenden SieResponse.AddHeader
. Siehe Thread SO: stackoverflow.com/questions/22313167/...Um anzuzeigen Datei (txt zum Beispiel):
So laden Sie eine Datei herunter (z. B. txt):
Hinweis: Um eine Datei herunterzuladen, müssen wir das Argument fileDownloadName übergeben
quelle
Inline
Eigenschaft in der Inhaltsdisposition kann ich die Möglichkeit zum Festlegen des Dateinamens vom Verhalten beim Erzwingen des Herunterladens trennen oder nicht.Ich glaube, diese Antwort ist sauberer (basierend auf https://stackoverflow.com/a/3007668/550975 ).
quelle
application/octet-stream
und dies dennoch dazu führte, dass die Datei heruntergeladen und nicht angezeigt wurde, scheint sie kompatibel zu sein.FileVirtualPath -> Research \ Global Office Review.pdf
quelle
Der folgende Code hat für mich funktioniert, um eine PDF-Datei von einem API-Dienst abzurufen und an den Browser zu senden - ich hoffe, es hilft;
quelle
Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider
Die Aktionsmethode muss FileResult entweder mit einem Stream, Byte [] oder einem virtuellen Pfad der Datei zurückgeben. Sie müssen auch den Inhaltstyp der heruntergeladenen Datei kennen. Hier ist ein Beispiel für eine (schnelle / schmutzige) Dienstprogrammmethode. Beispielvideolink So laden Sie Dateien mit asp.net core herunter
quelle
Wenn Sie wie ich beim Erlernen von Blazor über Razor-Komponenten zu diesem Thema gekommen sind, müssen Sie etwas über den Tellerrand hinaus denken, um dieses Problem zu lösen. Es ist ein kleines Minenfeld, wenn (auch wie ich) Blazor Ihr erster Ausflug in die Welt des MVC-Typs ist, da die Dokumentation für solche „einfachen“ Aufgaben nicht so hilfreich ist.
Zum Zeitpunkt des Schreibens können Sie dies mit Vanilla Blazor / Razor nicht erreichen, ohne einen MVC-Controller für den Dateidownload-Teil einzubetten. Ein Beispiel hierfür ist wie folgt:
Stellen Sie als Nächstes sicher, dass Ihr Anwendungsstart (Startup.cs) für die korrekte Verwendung von MVC konfiguriert ist und die folgende Zeile vorhanden ist (fügen Sie sie hinzu, wenn nicht):
.. und ändern Sie schließlich Ihre Komponente, um beispielsweise eine Verknüpfung mit dem Controller herzustellen (iteratives Beispiel unter Verwendung einer benutzerdefinierten Klasse):
Hoffentlich hilft dies jedem, der Probleme hatte (wie ich!), Eine angemessene Antwort auf diese scheinbar einfache Frage im Reich von Blazor zu finden…!
quelle