Quelle est la différence entre les quatre résultats de fichiers dans ASP.NET MVC

136

ASP.NET a quatre types différents de résultats de fichiers:

  • FileContentResult: envoie le contenu d'un fichier binaire à la réponse.
  • FilePathResult: envoie le contenu d'un fichier à la réponse
  • FileResult: renvoie la sortie binaire à écrire dans la réponse
  • FileStreamResult: envoie du contenu binaire à la réponse à l'aide d'une instance Stream

Ces descriptions sont tirées de MSDN et, à l'exception de FileStreamResult, les trois premiers sons identiques. Alors, quelle est la différence entre eux?

Robert MacLean
la source

Réponses:

176

FileResult est une classe de base abstraite pour toutes les autres.

  • FileContentResult - vous l'utilisez lorsque vous avez un tableau d'octets que vous souhaitez renvoyer sous forme de fichier
  • FilePathResult - lorsque vous avez un fichier sur le disque et que vous souhaitez retourner son contenu (vous donnez un chemin)
  • FileStreamResult - vous avez un flux ouvert, vous souhaitez renvoyer son contenu sous forme de fichier

Cependant, vous devrez rarement utiliser ces classes - vous pouvez simplement utiliser l'une des Controller.Filesurcharges et laisser ASP.NET MVC faire la magie pour vous.

maciejkow
la source
29

Excellente question ... et mérite plus de détails. Je me retrouve ici à la suite d'une situation intéressante. Nous livrions des pièces jointes PDF via l'environnement MVC3 / C #. Notre code a été publié et nous avons commencé à recevoir des réponses de nos clients indiquant que les téléchargements se comportaient étrangement lorsqu'ils utilisaient Chrome et que le type de fichier était converti en 'pdf-, attachment.pdf-, attachment'. Ouais ... vous l'avez ... le tout. Ainsi, on pourrait le réécrire pour qu'il soit juste 'pdf' et le fichier serait toujours sauvegardé intact, mais quel bordel!

Donc, pour décrire la situation initiale, nous avons défini l'en-tête 'Content-Disposition' puis renvoyé un FileContentResult ...

var cd = new System.Net.Mime.ContentDisposition
            {
                FileName = result.Attachment.FileName,
                Inline = false
            };
            Response.AppendHeader("Content-Disposition", cd.ToString());

return File(result.Attachment.Data, MimeExtensionHelper.GetMimeType(result.Attachment.FileName), result.Attachment.FileName);

Semblait bien. A bien fonctionné dans IE. J'ai donc fait des recherches et essayé d'implémenter FileStreamResult à la place (en conservant le setter Content-Disposition):

MemoryStream dataStream = new MemoryStream();
dataStream.Write(result.Attachment.Data, 0, result.Attachment.Data.Length);
dataStream.Position = 0;
return new FileStreamResult(dataStream, MimeExtensionHelper.GetMimeType(result.Attachment.FileName));

Cela a résolu le problème dans Chrome! Hmmm ... mais pourquoi diable devrais-je prendre mon tableau d'octets parfaitement bon et le diffuser, puis le renvoyer via ceci pour que le nom du fichier fonctionne correctement?

Puis vint le Fiddler.

Avec FileContentResult, j'ai 2 Content-Dispositions dans l'en-tête. Avec FileStreamResult, j'en ai 1.

FileContentResult ajoute un en-tête Content-Disposition lors de la fourniture du nom de fichier et Chrome considère les multiples de cet en-tête comme une erreur.

Réaction étrange ... mais certainement une bonne à savoir.

beauXjames
la source
3
Juste un conseil, dans .NET 4+, vous pouvez utiliser System.Web.MimeMapping.GetMimeMapping(filename)pour rassembler le type mime si vous ne pouvez pas y accéder facilement.
GONeale
4
Fournir un nom de fichier à un Filerésultat signifie définir sa FileDownloadNamepropriété, qui définit les en- Content-Dispositiontêtes pour vous. Et il prend correctement en charge les noms de fichiers utf-8, ce qui n'aide pas la ContentDispositionclasse (voir mon commentaire ici pour plus de détails).
Frédéric
1
Oui, merci @ Frédéric, vous seul sur tous les posts SO m'avez expliqué ce qui se passait!
Nacht