Estou com um problema ao enviar arquivos armazenados em um banco de dados de volta para o usuário no ASP.NET MVC. O que eu quero é uma visualização listando dois links, um para exibir o arquivo e permitir que o tipo de mim enviado ao navegador determine como ele deve ser tratado e o outro para forçar um download.
Se eu optar por exibir um arquivo chamado SomeRandomFile.bak
e o navegador não tiver um programa associado para abrir arquivos desse tipo, não tenho problemas com o padrão do comportamento do download. No entanto, se eu optar por exibir um arquivo chamado SomeRandomFile.pdf
ou SomeRandomFile.jpg
desejar que ele seja simplesmente aberto. Mas também quero manter um link de download ao lado para poder forçar um prompt de download, independentemente do tipo de arquivo. Isso faz sentido?
Eu tentei FileStreamResult
e funciona para a maioria dos arquivos; seu construtor não aceita um nome de arquivo por padrão; portanto, arquivos desconhecidos recebem um nome de arquivo com base na URL (que não conhece a extensão a ser atribuída com base no tipo de conteúdo). Se forçar o nome do arquivo especificando-o, perco a capacidade do navegador de abrir o arquivo diretamente e recebo uma solicitação de download. Mais alguém encontrou isso?
Estes são os exemplos do que eu tentei até agora.
//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};
Alguma sugestão?
ATUALIZAÇÃO:
Essas perguntas parecem impressionar muita gente, então pensei em publicar uma atualização. O aviso na resposta aceita abaixo, que foi adicionado por Oskar em relação aos personagens internacionais, é completamente válido, e eu o recebi algumas vezes devido ao uso da ContentDisposition
classe. Atualizei minha implementação para corrigir isso. Embora o código abaixo seja da minha versão mais recente desse problema em um aplicativo ASP.NET Core (Full Framework), ele deve funcionar com alterações mínimas em um aplicativo MVC mais antigo, desde que eu esteja usando a 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
}