ASP .NET MVC - Fazendo o download de arquivos


Se você conhece a filosofia de uma aplicação ASP .NET MVC já deve saber que as Views são controladas diretamente pelas Action de um Controller.

Cada método Action da classe Controller retorna um ActionResult que por sua vez é uma classe abstrata. Temos várias classes herdadas desta classe e cada uma delas são usadas em casos específicos. Uma dessas classes herdadas é a classe FileResult.

Esta classe é usada para enviar o conteúdo de um arquivo binário para um response.

Assim os métodos declarados no controlador retornam classes derivadas de ActionResult sendo que o tipo retornado depende diretamente da tarefa executada e do método usado.

A seguir temos uma relação das classes derivadas de ActionResult e seus métodos:

Classe Derivada de ActionResult Métodos Descrição Resumida
ViewResult View Usada para exibir uma view.
PartialViewResult PartialView Usada para exibir um userControl.
ContentResult Content Retorna texto puro.
EmptyResult   Não retorna nada.
FileResult File A saída é o conteúdo de um arquivo.
HttpUnauthorizedResult   Representa um acesso não autorizado.
JavaScriptResult JavaScript Retorna conteúdo JavaScript
JsonResult Json Retorna anotações Json.
RedirecResult Redirect Redireciona o usuário para outra página.
HttpNotFoundResult   Retorna uma página não encontrada.
HttpStatusCodeResult Http definido Retorna um código de status.

No exemplo deste artigo veremos como usar a Action FileResult para fazer o download de arquivos em uma aplicação ASP .NET MVC 3.

Abra o Visual Studio 2010 Express for Web e no menu File clique em New Project;

Selecione o template Visual C# -> Web -> ASP .NET MVC 3 Web Application e informe o nome EnviandoArquivos_Mvc, e clique no botão OK;

A seguir selecione Internet Application e o View Engine Razor e clique no botão OK;

Será criado uma solução contendo um projeto com uma estrutura de uma aplicação MVC padrão contendo as pastas Models, Views , Controllers, os arquivos de configuração, e arquivos de controlador e views.

Vamos incluir uma pasta na raiz da aplicação chamada Arquivos onde vamos armazenar alguns arquivos PDFs que iremos tratar em nossa aplicação.

Clique com o botão direito do mouse sobre o projeto e selecione Add -> New Folder e informe o nome Arquivos.

A seguir clique com o botão direito do mouse sobre a pasta Arquivos e selecione Add -> Existing Item e selecione alguns arquivos PDF para incluir nesta pasta.

Começando pelo Model

Vamos iniciar definindo o Model da nossa aplicação MVC onde iremos criar uma classe com um método que permite obter os arquivos da nossa aplicação e uma classe onde vamos definir informações básicas dos arquivos que vamos tratar.

Clique com o botão direito do mouse sobre a pasta Models e clique em Add -> Class informando o nome Arquivos.cs;

A seguir defina o código abaixo na classe Arquivos:

 public class Arquivos
    {
        public int arquivoID { get; set; }
        public string arquivoNome { get; set; }
        public string arquivoCaminho { get; set; }
    }

Agora vamos definir o método para obter os arquivos no Model.

Clique com o botão direito do mouse sobre a pasta Models e clique em Add -> Class informando o nome ModelArquivos.cs;

Defina os seguintes namespace no arquivo ModelArquivos.cs:

using System.Collections.Generic;
using System.IO;
using System.Web.Hosting;

A seguir vamos definir o método GetArquivos() na classe ModelArquivos conforme o código abaixo:

  public List<Arquivos> GetArquivos()
        {
            List<Arquivos> lstArquivos = new List<Arquivos>();
            //DirectoryInfo dirInfo = new DirectoryInfo(HostingEnvironment.MapPath("~/Arquivos"));
           
DirectoryInfo dirInfo = new DirectoryInfo("c:/dados/Arquivos/");

            int i = 0;
            foreach (var item in dirInfo.GetFiles())
            {
                lstArquivos.Add(new Arquivos()
                {
                    arquivoID = i + 1,
                    arquivoNome = item.Name,
                    arquivoCaminho = dirInfo.FullName + @"\" + item.Name
                });
                i = i + 1;
            }
            return lstArquivos;
        }

Observe que eu defini o local para download de arquivos PDF na pasta c:\dados\Arquivos que deve ser uma pasta do servidor.

Definindo o Controlador

Vamos definir o controlador contendo os métodos Action.

Clique com o botão direito do mouse sobre a pasta Controllers e a seguir clique em Add->Controller;

Informe o nome ArquivosController e selecione o template Empty Controller e clique em Add;

Digite o código abaixo no controlador criado acima:

using System;
using System.Linq;
using System.Web.Mvc;
using EnviandoArquivos_Mvc.Models;

namespace EnviandoArquivos_Mvc.Controllers
{
    public class ArquivosController : Controller
    {
        ModelArquivos oModelArquivos = new ModelArquivos();

        // GET: /Reports/
        public ActionResult Index()
        {
            var _arquivos = oModelArquivos.GetArquivos();
            return View(_arquivos);
        }

        public FileResult Download(string id)
        {
            int _arquivoId = Convert.ToInt32(id);
            var arquivos = oModelArquivos.GetArquivos();

            string nomeArquivo = (from arquivo in arquivos
                                              where arquivo.arquivoID == _arquivoId
                                              select arquivo.arquivoCaminho).First();                       

            string contentType = "application/pdf";
            //Os parametros para o arquivo são
            //1. o caminho do aruivo on servidor
            //2. o tipo de conteudo do tipo MIME
            //3. o parametro para o arquivos salvo pelo navegador

            return File(nomeArquivo, contentType,"Report.pdf");
        }
    }
}

Neste arquivos temos :

O método Action "Download" aceita o id do arquivo (arquivoID) a partir da View e consulta a lista de arquivos retornados a partir do método GetArquivos.

Após consultar a lista de arquivos ele obtém o caminho do arquivo e também define o tipo do conteúdo que é MIME. Esta informação é necessária ao navegador para decidir como lidar com o arquivo. Nesse caso, define-se como aPDF.

O método retorna um objeto do tipo 'FilePathResult', esta é a classe herdada de FileResult.

FilePathResult aceita três parâmetros: O primeiro é o caminho do arquivo a ser baixado. O segundo é o tipo de conteúdo. O terceiro parâmetro é o nome do arquivo para download. Este é um parâmetro opcional, em seguida, o navegador irá realizar o download.

Criando a View

Vamos definir a view que irá criar a interface com o usuário.

Clique com o botão direito no interior do método Index do controller ArquivosController e clique em Add View;

Aceite os valores padrão da janela Add View e clique em Add;

A seguir ajuste o código criado por padrão na view conforme abaixo:

@model IEnumerable<EnviandoArquivos_Mvc.Models.Arquivos>

@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            arquivoID
        </th>
        <th>
            arquivoNome
        </th>
        <th></th>
    </tr>
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.arquivoID)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.arquivoNome)
        </td>
        <td>
            @Html.ActionLink("Download", "Download", new { id = item.arquivoID })
        </td>
    </tr>
}
</table>

Antes de testarmos a aplicação abra o arquivo _Layout.cshtml da pasta /Shared e inclua linha de código para criar o menu Arquivos:

<li>@Html.ActionLink("Arquivos", "Index", "Arquivos")</li>

Executando a aplicação iremos obter a seguinte página:

Clicando na opção Arquivos iremos obter a lista de arquivos no formato definido, no caso PDF, para download:

Clicando no link Download teremos a janela de download para baixa do arquivo:

Pegue o projeto completo aqui: EnviandoArquivos_Mvc.zip

Rom 8:5 Pois os que são segundo a carne inclinam-se para as coisas da carne; mas os que são segundo o Espírito para as coisas do Espírito.

Rom 8:6 Porque a inclinação da carne é morte; mas a inclinação do Espírito é vida e paz.

Referências:


José Carlos Macoratti