Je rencontre un problème pour renvoyer à l'utilisateur des fichiers stockés dans une base de données en ASP.NET MVC. Ce que je veux, c'est une vue listant deux liens, l'un pour afficher le fichier et laisser le mimetype envoyé au navigateur déterminer comment il doit être traité, et l'autre pour forcer un téléchargement.
Si je choisis de visualiser un fichier appelé SomeRandomFile.bak
et que le navigateur n'a pas de programme associé pour ouvrir des fichiers de ce type, alors je n'ai aucun problème à ce qu'il adopte par défaut le comportement de téléchargement. Toutefois, si je choisis d'afficher un fichier appelé SomeRandomFile.pdf
o SomeRandomFile.jpg
Je veux que le fichier s'ouvre simplement. Mais je veux également conserver un lien de téléchargement sur le côté afin de pouvoir forcer une invite de téléchargement quel que soit le type de fichier. Cela a-t-il un sens ?
J'ai essayé FileStreamResult
et cela fonctionne pour la plupart des fichiers, son constructeur n'accepte pas de nom de fichier par défaut, donc les fichiers inconnus se voient attribuer un nom de fichier basé sur l'URL (qui ne sait pas quelle extension donner en fonction du type de contenu). Si je force le nom de fichier en le spécifiant, je perds la possibilité pour le navigateur d'ouvrir directement le fichier et j'obtiens une invite de téléchargement. Quelqu'un d'autre a-t-il rencontré ce problème ?
Voici les exemples de ce que j'ai essayé jusqu'à présent.
//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};
Des suggestions ?
UPDATE : Cette question semble toucher une corde sensible chez beaucoup de gens, alors j'ai pensé poster une mise à jour. L'avertissement sur la réponse acceptée ci-dessous qui a été ajouté par Oskar concernant les caractères internationaux est tout à fait valable, et je l'ai rencontré à plusieurs reprises en utilisant l'option ContentDisposition
la classe. J'ai depuis mis à jour mon implémentation pour corriger cela. Bien que le code ci-dessous provienne de mon incarnation la plus récente de ce problème dans une application ASP.NET Core (Full Framework), il devrait également fonctionner avec des changements minimes dans une application MVC plus ancienne, puisque j'utilise la classe System.Net.Http.Headers.ContentDispositionHeaderValue
classe.
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
}