ASP .NET MVC - Retornando arquivos de uma Web API


 Hoje veremos como retornar arquivos a partir de uma Web API usando a ASP .NET MVC 5.     

Uma Web API pode ser vista como um conjunto de serviços expostos via web com o objetivo de integrar sua aplicação a diversos tipos de clientes que queiram usar os serviços. Esses serviços são usados como requisições HTTP e retornam uma resposta em um formato específico como XML,JSON, etc. Essa resposta pode ser uma informação de  um repositório de dados, o retorno de uma operação, etc. O cliente pode ser uma página web, uma aplicação desktop, uma aplicação mobile, etc.

Dessa forma , uma Web API  é uma API sobre a web (Serviços REST HTTP), sendo que a ASP.NET Web API é um framework que permite que você construa Web APIs, ou seja, serviços baseados em HTTP no topo do .NET Framework usando uma convenção de base e um modelo de programação semelhante ao da ASP.NET MVC.

Quando estamos trabalhando com o serviço REST, é muito importante entender como enviar arquivos. Neste artigo, vamos discutir como retornar arquivos nos formatos PDF/Word/Excel,Zip, etc, a partir de um serviço ASP .NET Web API .

Vamos supor que tenhamos como requisito enviar um arquivo com base no tipo de arquivo fornecido para a solicitação de serviço. Por exemplo, quando enviamos o tipo de arquivo como PDF, o serviço retornará o arquivo PDF, se enviarmos um tipo Doc, o serviço retornará o documento do Word, se for o tipo zip enviaremos um arquivo zipado, etc.

Não podemos apenas enviar o arquivo diretamente, antes, temos que realizar alguns procedimentos que são descritos a seguir:

A propriedade ContentType tem um papel muito importante no envio dos arquivos. O cabeçalho Content-Type é utilizado para indicar o tipo de arquivo do recurso.

Para saber os tipos MIME suportados consulte este link: https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Basico_sobre_HTTP/MIME_types/Complete_list_of_MIME_types

Há dois tipo MIME que são importantes para tipos padrões:

No nosso exemplo vou usar o valor application/octet-strem para esta propriedade, pois vamos querer enviar tipos diferentes de arquivos, e, porque conhecemos e confiamos no conteúdo que estamos disponibilizando.

Então mãos à obra...

Criando a Web API no VS 2017

Abra o VS 2017 Community e selecione File ->New Project;  (ou crie apenas um arquivo HTML)

Selecione Web e o template ASP .NET Web Application e informe o nome WebAPI_Arquivos e clique em OK;

A seguir inclua marque a opção Empty e Web API e clique no botão OK:

Com isso teremos um projeto pronto, conforme a figura a seguir, onde iremos criar a nossa Web API.

Clique com o botão direito sobre a pasta Controllers e  a seguir clique em Add->Controller e selecione a opção Web API 2 Controller - Empty e clique no botão Add:

Informe o nome ArquivosController.

A seguir inclua o código abaixo neste controlador:

using System.IO;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace WebAPI_Arquivos.Controllers
{
    public class ArquivosController : ApiController
    {
        string arquivo_Pdf = @"C:\Dados\PDF\teste.pdf";
        string arquivo_xls = @"C:\Dados\XLS\teste.xls";
        string arquivo_doc = @"C:\Dados\DOC\teste.docx";
        string arquivo_zip = @"C:\Dados\ZIP\teste.zip";
        [HttpGet]
        [ActionName("BaixarArquivo")]
        public IHttpActionResult BaixarArquivo(string formato)
        {
            string reqArquivo = formato.ToLower() == "pdf" ? arquivo_Pdf : (formato.ToLower() == "xls" ? arquivo_xls
 : (formato.ToLower() == "doc" ? arquivo_doc : arquivo_zip));
            string arquivoNome = "teste." + formato.ToLower();
            //converte arquivos em um array de bytes
            var dataBytes = File.ReadAllBytes(reqArquivo);
            //adiciona bytes ao memory stream   
            var dataStream = new MemoryStream(dataBytes);
            return new ArquivoResult(dataStream, Request, arquivoNome);
        }
    }
    public class ArquivoResult : IHttpActionResult
    {
        MemoryStream arquivoStuff;
        string nomeDoArquivo;
        HttpRequestMessage httpRequestMessage;
        HttpResponseMessage httpResponseMessage;

        public arquivoResult(MemoryStream data, HttpRequestMessage request, string filename)
        {
            arquivoStuff = data;
            httpRequestMessage = request;
            nomeDoArquivo = filename;
        }

        public System.Threading.Tasks.Task<HttpResponseMessage> ExecuteAsync(System.Threading
.CancellationToken cancellationToken)
        {
            httpResponseMessage = httpRequestMessage.CreateResponse(HttpStatusCode.OK);
            httpResponseMessage.Content = new StreamContent(arquivoStuff);
            httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.
ContentDispositionHeaderValue("attachment");
            httpResponseMessage.Content.Headers.ContentDisposition.FileName = nomeDoArquivo;
            httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers
.MediaTypeHeaderValue("application/octet-stream");
            return System.Threading.Tasks.Task.FromResult(httpResponseMessage);
        }
    }
}

No código estamos definindo os arquivos que desejamos servir e a seguir criamos o método Action BaixarArquivo definido como um GET que vai receber como parâmetro o tipo de arquivo a ser baixado.

No método ArquivoResult realizarmos o processamento do download definindo o cabeçalho para o cliente.

Para poder baixar os arquivos temos que definir o formato do mesmo via URL e para isso vamos ajustar o arquivo WebApiConfig definindo o parâmetro opcional com o nome de formato:

using System.Web.Http;
namespace WebAPI_Arquivos
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            // Web API routes
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{formato}",
                defaults: new { formato = RouteParameter.Optional }
            );
        }
    }
}

Após isso basta informar na URL a chamada no seguinte formato:  servidor:porta/api/Arquivos/BaixarArquivo?formato={doc,xls,pdf,zip}

Exemplos:

Executando o projeto iremos obter o seguinte resultado:

Podemos melhorar o projeto tornando-o mais amigável mas a objetivo principal era retornar os arquivos definidos.

Pegue o projeto aqui :   WebAPI_Arquivos.zip (sem as referências)

"E disse-lhe um: Senhor, são poucos os que se salvam? E ele lhe respondeu:
Porfiai por entrar pela porta estreita; porque eu vos digo que muitos procurarão entrar, e não poderão."

Lucas 13:23,24

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Referências:


José Carlos Macoratti