ASP.NET MVC 4: Realizando Upload e download de arquivos
Veja nesse artigo como funciona o desenvolvimento em camada através do desenvolvimento de uma aplicação que fará o download e o upload de imagens.
Neste artigo desenvolveremos uma aplicação em ASP.NET MVC 4 que será responsável por realizar o upload de imagens e também disponibilizá-las em seguida para download para o usuário, com o intuito principal de auxiliar desenvolvedores que estão em processo de migração para o MVC Framework. Neste artigo usaremos o Visual Studio 2012 e o plugin jQuery MultiFile.
Iniciaremos entendendo a filosofia de como o MVC trabalha com arquivos e diretórios: o ActionResult é a classe abstrata retornada por cada método das Actions. Várias classes herdam da ActionResult, inclusive a FileResult, que é responsável pelo envio de conteúdo do arquivo binário para o response. Vamos ver a seguir um pouco sobre essas classes:
- ViewResult : Responsável por exibir uma View.
- ContentResult : Retorna apenas texto.
- FileResult : A saída é o conteúdo de um arquivo.
- JavaScriptResult : A saída para o conteúdo de um arquivo JavaScript.
- JSonResult : Retorna as anotações do Json.
Criando o Projeto
Vamos montar nosso ambiente criando uma aplicação ASP.NET MVC 4 Web Aplicattion usando o template InternetApllication e Razor como viewengine com o nome de MvcDownUpload no visual studio 2012, como mostrado nas Figuras 1 e 2.
De início, nos preocuparemos em montar a estrutura da nossa aplicação. Para isso, criaremos uma classe Model que representará o arquivo com que a aplicação irá trabalhar. Nela irá conter as seguintes propriedades: Nome, Tamanho, Tipo e Caminho, como mostrado na Listagem 1.
public class UploadFileResult
{
public int IDArquivo { get; set; }
public string Nome { get; set; }
public int Tamanho{ get; set; }
public string Tipo{ get; set; }
public string Caminho { get; set; }
}
No próximo passo criaremos nossa classe Controller FileUpload que será responsável por realizar todo o trabalho de importação do arquivo, como mostrado na Listagem 2.
public class FileUploadController : Controller
{
//
// GET: /FileUpload/
public ActionResult Index()
{
return View();
}
public ActionResult FileUpload()
{
int arquivosSalvos = 0;
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase arquivo = Request.Files[i];
//Suas validações ......
//Salva o arquivo
if (arquivo.ContentLength > 0)
{
var uploadPath = Server.MapPath("~/Content/Uploads");
string caminhoArquivo = Path.Combine(@uploadPath,
Path.GetFileName(arquivo.FileName));
arquivo.SaveAs(caminhoArquivo);
arquivosSalvos++;
}
}
ViewData["Message"] = String.Format(" arquivo(s) salvo(s) com sucesso.",
arquivosSalvos);
return View("Upload");
}
}
Agora precisaremos adicionar o plugin jQuery MultiFile ao nosso projeto. Para isso, clicaremos com o botão direito na pasta scripts e em seguida add existing item. Em seguida, localize onde foram salvos seus arquivos do plugin e clique em Add para todos, como mostrado na Figura 3.
Por último, criaremos nossa camada de interface, adicionando de início duas Views chamadas index e upload, como mostrado nas Figuras 4 e 5.
Como vocês puderam notar, a estrutura das views de início é bem simples, formada por tags básicas do HTML, mas para fazermos nosso componente de upload funcionar devemos implementar uma função JavaScript e adicionarmos as referências aos arquivos .Js do plugin na tag Head da view Upload, como na Listagem 3.
<link href="~/Content/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/bootstrap/bootstrap-theme.min.css" rel="stylesheet" />
<script src="~/Scripts/jquery-1.9.1.min.js"></script>
<script src="~/Scripts/jquery.ui.widget.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
<script src="~/Scripts/jquery.MultiFile.js"></script>
<script src="../../Scripts/jquery-1.3.2.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#file').MultiFile({
accept: 'gif|jpg',
max: 3,
STRING: {
remove: 'Remover',
denied: 'Tipo do arquivo inválido $ext!',
duplicate: 'Esse arquivo já foi selecionado:\n$file!'
}
});
});
</script>
Executaremos nossa aplicação para verificarmos como está o funcionamento desse primeiro fluxo, conforme mostrado na Figura 6.
Na view Upload escolheremos o arquivo local que desejamos mandar e clicaremos no botão enviar, a aplicação executará nossa Action FileUpload criada anteriormente e realizará a importação do arquivo como mostrado na Figura 7.
Para comprovarmos que o arquivo foi importado, basta irmos à pasta onde escolhemos que nossos arquivos seriam salvos, que no caso é Content/Uploads, e verificarmos a existência dos mesmos, como mostrado na Figura 8.
Na segunda parte trataremos de desenvolver a lógica que listará nossos arquivos e os disponibilizará para download, onde primeiramente criaremos no nosso model UploadResult um método responsável por “pegar” os arquivos disponíveis, como mostrado na Listagem 4.
public List<UploadFileResult> ListaArquivos()
{
List<UploadFileResult> lstArquivos = new List<UploadFileResult>();
DirectoryInfo dirInfo = new DirectoryInfo(Server.MapPath("~/Content/Uploads"));
int i = 0;
foreach (var item in dirInfo.GetFiles())
{
lstArquivos.Add(new UploadFileResult()
{
IDArquivo = i + 1,
Nome = item.Name,
Caminho = dirInfo.FullName + @"\" + item.Name
});
i = i + 1;
}
return lstArquivos;
Em seguida, definiremos o nosso Controller responsável pelos downloads, como mostrado na Listagem 5.
public class DownloadController : Controller
{
UploadFileResult oModelArquivos = new UploadFileResult();
public ActionResult Index()
{
var _arquivos = oModelArquivos.ListaArquivos();
return View(_arquivos);
}
public FileResult Download(string id)
{
int _arquivoId = Convert.ToInt32(id);
var arquivos = oModelArquivos.ListaArquivos();
string nomeArquivo = (from arquivo in arquivos
where arquivo.IDArquivo == _arquivoId
select arquivo.Caminho).First();
string contentType = "application/pdf";
return File(nomeArquivo, contentType, "Report.pdf");
}
}
Na Listagem 6 criaremos nossa view de interface com o usuário.
@model IList<MvcDownUpload.Models.UploadFileResult>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Importar Novo", "Upload")
</p>
<table>
<tr>
<th>
Codigo
</th>
<th>
Nome
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.IDArquivo)
</td>
<td>
@Html.DisplayFor(modelItem => item.Nome)
</td>
<td>
@Html.ActionLink("Download", "Download", new { id = item.IDArquivo })
</td>
</tr>
}
</table>
Note que criamos essa view do tipo do nosso model UploadFileResult para que assim pudéssemos ter acesso a suas propriedades e, a partir dele, executaremos nossa Action Download que disponibilizará o arquivo para o cliente. Para testarmos vamos executar nossa aplicação mais uma vez, como mostrado na Figura 9.
Ao clicarmos em um arquivo será disponibilizada a janela de download, como mostrado na Figura 10.
Para finalizarmos vamos dar uma melhorada na nossa aplicação tirando a amarração feita no código fonte para que o download seja gerado apenas em formato .pdf. Para isso, realizaremos uma pequena alteração na nossa Action de download, como mostra a Listagem 7.
public FileResult Download(string id)
{
int _arquivoId = Convert.ToInt32(id);
string contentType="";
var arquivos = oModelArquivos.ListaArquivos(Server.MapPath("~/Content/Uploads"));
string nomeArquivo = (from arquivo in arquivos
where arquivo.IDArquivo == _arquivoId
select arquivo.Caminho).First();
string extensao = Path.GetExtension(nomeArquivo);
string nomeArquivoV = Path.GetFileNameWithoutExtension(nomeArquivo);
if (extensao.Equals(".pdf"))
contentType = "application/pdf";
if (extensao.Equals(".JPG") || extensao.Equals(".GIF") || extensao.Equals(".PNG"))
contentType = "application/image";
return File(nomeArquivo, contentType, nomeArquivoV+extensao);
}
Fazendo isso assim que recuperarmos nosso arquivo escolhido para download pelo id, poderemos recuperar sua extensão e atribuirmos o contentType adequado.
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo