Qual é a diferença entre os quatro Resultados de Arquivo no ASP.NET MVC

136

O ASP.NET possui quatro tipos diferentes de resultados de arquivo:

  • FileContentResult: envia o conteúdo de um arquivo binário para a resposta.
  • FilePathResult: envia o conteúdo de um arquivo para a resposta
  • FileResult: Retorna a saída binária para gravar na resposta
  • FileStreamResult: envia conteúdo binário para a resposta usando uma instância do Stream

Essas descrições são obtidas no MSDN e, com exceção do FileStreamResult, os três primeiros são idênticos. Então, qual é a diferença entre eles?

Robert MacLean
fonte

Respostas:

176

FileResult é uma classe base abstrata para todas as outras.

  • FileContentResult - você o usa quando possui uma matriz de bytes que gostaria de retornar como um arquivo
  • FilePathResult - quando você tem um arquivo em disco e gostaria de retornar seu conteúdo (você indica um caminho)
  • FileStreamResult - você tem um fluxo aberto, deseja retornar seu conteúdo como um arquivo

No entanto, você raramente precisará usar essas classes - basta usar uma das Controller.Filesobrecargas e deixar o ASP.NET MVC fazer a mágica por você.

maciejkow
fonte
29

Ótima pergunta ... e merece mais detalhes. Eu me encontro aqui como resultado de uma situação interessante. Estávamos entregando alguns anexos em pdf por meio do ambiente MVC3 / C #. Nosso código foi lançado e começamos a receber respostas de nossos clientes de que os downloads estavam se comportando de maneira estranha quando estavam usando o Chrome e o tipo de arquivo estava sendo convertido para 'pdf-, attachment.pdf-, anexo'. Sim ... você entendeu ... a coisa toda. Então, alguém poderia reescrevê-lo para ser apenas 'pdf' e o arquivo ainda salvaria intacto, mas que bagunça!

Então, para descrever a situação inicial, estávamos configurando o cabeçalho 'Content-Disposition' e retornando um 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);

Parecia bom. Funcionou bem no IE. Então, fiz uma pesquisa e tentei implementar o FileStreamResult (mantendo o 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));

Foi corrigido o problema no Chrome! Hmmm ... mas por que diabos eu deveria ter que pegar minha matriz de bytes perfeitamente boa e transmiti-la e depois devolvê-la por isso para que o nome do arquivo funcionasse corretamente?

Então veio o Violinista.

Com FileContentResult, recebi 2 disposições de conteúdo no cabeçalho. Com FileStreamResult, obtive 1.

FileContentResult acrescenta um cabeçalho de Disposição de Conteúdo ao fornecer o Nome do arquivo e o Chrome considera vários deste cabeçalho como um erro.

Reação estranha ... mas definitivamente uma que é boa de saber.

beauXjames
fonte
3
Apenas uma dica: no .NET 4+, você pode usar System.Web.MimeMapping.GetMimeMapping(filename)para coletar o tipo mime se não puder acessá-lo facilmente.
GONeale
4
Fornecer um nome de arquivo para um Fileresultado significa definir sua FileDownloadNamepropriedade, que define os Content-Dispositioncabeçalhos para você. E ele suporta corretamente nomes de arquivos utf-8, o que não ContentDispositionajuda na classe (veja meu comentário aqui para mais detalhes).
Frédéric
1
Sim, obrigado @ Frédéric, você sozinho, de todas as postagens do SO, me explicou o que estava acontecendo!
Nacht