Estou trabalhando em um serviço da Web usando a nova WebAPI do ASP.NET MVC que servirá arquivos binários, principalmente .cab
e .exe
arquivos.
O seguinte método do controlador parece funcionar, o que significa que ele retorna um arquivo, mas está configurando o tipo de conteúdo para application/json
:
public HttpResponseMessage<Stream> Post(string version, string environment, string filetype)
{
var path = @"C:\Temp\test.exe";
var stream = new FileStream(path, FileMode.Open);
return new HttpResponseMessage<Stream>(stream, new MediaTypeHeaderValue("application/octet-stream"));
}
Existe uma maneira melhor de fazer isso?
asp.net
asp.net-mvc
asp.net-web-api
Josh Earl
fonte
fonte
Respostas:
Tente usar um simples
HttpResponseMessage
com suaContent
propriedade definida comoStreamContent
:Algumas coisas a serem observadas sobre o
stream
usado:Você não deve ligar
stream.Dispose()
, pois a API da Web ainda precisa acessá-la quando processar o método do controladorresult
para enviar dados de volta ao cliente. Portanto, não use umusing (var stream = …)
bloco. A API da Web descartará o fluxo para você.Verifique se o fluxo tem sua posição atual definida como 0 (ou seja, o início dos dados do fluxo). No exemplo acima, isso é um dado, pois você acabou de abrir o arquivo. No entanto, em outros cenários (como quando você escreve pela primeira vez alguns dados binários em a
MemoryStream
), certifique-se destream.Seek(0, SeekOrigin.Begin);
definirstream.Position = 0;
Com os fluxos de arquivos, especificar explicitamente a
FileAccess.Read
permissão pode ajudar a evitar problemas de direitos de acesso nos servidores da Web; As contas do pool de aplicativos IIS geralmente recebem apenas direitos de leitura / lista / execução de acesso ao wwwroot.fonte
using
ao resultado (HttpResponseMessage
) ou ao próprio fluxo, pois eles ainda serão usados fora do método. Como o @Dan mencionou, eles são descartados pela estrutura após o envio da resposta ao cliente.Para a API da Web 2 , você pode implementar
IHttpActionResult
. Aqui está o meu:Então, algo como isso no seu controlador:
E aqui está uma maneira de dizer ao IIS para ignorar solicitações com uma extensão, para que a solicitação chegue ao controlador:
fonte
async
modificador na assinatura do método e remover a criação de uma tarefa completamente: gist.github.com/ronnieoverby/ae0982c7832c531a9022Para aqueles que usam o .NET Core:
Você pode usar a interface IActionResult em um método de controlador de API, assim ...
Este exemplo é simplificado, mas deve passar o ponto. Em .NET Núcleo esse processo é por isso muito mais simples do que nas versões anteriores do .NET - ou seja, nenhum tipo de resposta definição, conteúdo, cabeçalhos, etc.
Além disso, é claro que o tipo MIME do arquivo e a extensão dependerão das necessidades individuais.
Referência: SO Postar resposta por @NKosi
fonte
Enquanto a solução sugerida funciona bem, há outra maneira de retornar uma matriz de bytes do controlador, com o fluxo de resposta formatado corretamente:
Infelizmente, o WebApi não inclui nenhum formatador para "application / octet-stream". Há uma implementação aqui no GitHub: BinaryMediaTypeFormatter (há pequenas adaptações para fazê-lo funcionar na webapi 2, as assinaturas de método foram alteradas).
Você pode adicionar este formatador à sua configuração global:
Agora, o WebApi deve ser usado
BinaryMediaTypeFormatter
se a solicitação especificar o cabeçalho Aceitar correto.Eu prefiro esta solução porque um controlador de ação retornando byte [] é mais confortável para testar. No entanto, a outra solução permite maior controle se você deseja retornar outro tipo de conteúdo que não seja "application / octet-stream" (por exemplo, "image / gif").
fonte
Para qualquer pessoa que tenha o problema de a API ser chamada mais de uma vez durante o download de um arquivo bastante grande usando o método na resposta aceita, defina o buffer de resposta como true System.Web.HttpContext.Current.Response.Buffer = true;
Isso garante que todo o conteúdo binário seja armazenado em buffer no servidor antes de ser enviado ao cliente. Caso contrário, você verá várias solicitações sendo enviadas ao controlador e, se não tratá-las adequadamente, o arquivo ficará corrompido.
fonte
Buffer
propriedade foi preterida em favor deBufferOutput
. O padrão étrue
.A sobrecarga que você está usando define a enumeração dos formatadores de serialização. Você precisa especificar o tipo de conteúdo explicitamente, como:
fonte
Content Type: application/json
no Fiddler. OContent Type
parece estar definida corretamente se eu quebrar antes de retornar ahttpResponseMessage
resposta. Mais alguma ideia?Você poderia tentar
fonte