Upload de arquivo do MVC 4 Razor

249

Eu sou novo no MVC 4 e estou tentando implementar o Controle de Upload de Arquivos no meu site. Não consigo encontrar o erro. Estou recebendo um valor nulo no meu arquivo.

Controlador:

public class UploadController : BaseController
    {
        public ActionResult UploadDocument()
        {
            return View();
        }

       [HttpPost]
       public ActionResult Upload(HttpPostedFileBase file)
       {
           if (file != null && file.ContentLength > 0)
           {
               var fileName = Path.GetFileName(file.FileName);
               var path = Path.Combine(Server.MapPath("~/Images/"), fileName);
               file.SaveAs(path);
           }

           return RedirectToAction("UploadDocument");
        }
    }

Visão:

@using (Html.BeginForm("Upload", "Upload", FormMethod.Post, new { enctype = "multipart/form-data" }))
{ 
    <input type="file" name="FileUpload" />
    <input type="submit" name="Submit" id="Submit" value="Upload" />
}
Liam
fonte
possível duplicação do upload
Liam
1
você só tem que mudar public ActionResult Upload (arquivo HttpPostedFileBase) <input type = nome "file" = "FileUpload" />
Muhammad Asad
confira minha implementação aqui stackoverflow.com/a/40990080/4251431
Basheer AL-MOMANI
2
Faltando o enctypeno formulário de me custou uma hora
Savage
Onde está a conexão entre o método Upload () e o botão. Deve haver um evento onClick? Novo no asp.net Eu sou
pnizzle

Respostas:

333

O parâmetro Uploaddo método HttpPostedFileBasedeve ter o mesmo nome que o file input.

Então, basta alterar a entrada para isso:

<input type="file" name="file" />

Além disso, você pode encontrar os arquivos em Request.Files:

[HttpPost]
public ActionResult Upload()
{
     if (Request.Files.Count > 0)
     {
         var file = Request.Files[0];

         if (file != null && file.ContentLength > 0)
         {
            var fileName = Path.GetFileName(file.FileName);
            var path = Path.Combine(Server.MapPath("~/Images/"), fileName);
            file.SaveAs(path);
         }
     }

     return RedirectToAction("UploadDocument");
 }
Cristi Pufu
fonte
2
não será Index out of boundsexceção, caso não exista arquivo na Request.Filescoleção ..?
Shashwat
2
Na verdade, ele vai jogar ArgumentOutOfRangeException, mas você está certo, eu atualizei
Cristi Pufu
2
Lembre-se de que os parâmetros do Html.BeginForm são o nome da ação e o nome do controlador (sem o postfix 'controller'. Por exemplo: Home em vez de HomeController). Outra coisa importante é não incluir o <form> tag dentro, porque é o BeginForm que abre o tag
pocjoc
5
Em outras palavras - O nome da propriedade do seu modelo de visualização deve corresponder ao nome do tipo de entrada. Se a sua viewmodelpropriedade é nomeado AgentPhotoem seguida, você deve ter o seguinte em seu ponto de vista:<input type="file" name="AgentPhoto"/>
Dayan
var path = Path.Combine(Server.MapPath("~/Images/"), fileName);, a classe "Servidor" não encontrada, qual pacote usa?
Danilo Pádua
65

Esclarecendo. Modelo:

public class ContactUsModel
{
    public string FirstName { get; set; }             
    public string LastName { get; set; }              
    public string Email { get; set; }                 
    public string Phone { get; set; }                 
    public HttpPostedFileBase attachment { get; set; }

Ação pós

public virtual ActionResult ContactUs(ContactUsModel Model)
{
 if (Model.attachment.HasFile())
 {
   //save the file

   //Send it as an attachment 
    Attachment messageAttachment = new Attachment(Model.attachment.InputStream,       Model.attachment.FileName);
  }
}

Finalmente, o método Extension para verificar o hasFile

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace AtlanticCMS.Web.Common
{
     public static class ExtensionMethods 
     {
         public static bool HasFile(this HttpPostedFileBase file)
         {
             return file != null && file.ContentLength > 0;
         }        
     }
 }
Bishoy Hanna
fonte
anexo público HttpPostedFileBase {get; conjunto; } / anexo não é um identificador
Codeone 24/11
Eu acho que Cola está se referindo ao tipo de anexo que não está sendo definido.
Karson
2
A visualização pode ser usada conforme descrito pelo usuário2028367. Na verdade, eu esqueci de incluir o novo {enctype = "multipart / form-data"} na parte Html.BeginForm, por isso não consegui visualizar o arquivo na minha ação. Ótima resposta. +1 para exibição na classe Model e no método Extension.
Arjun #
@BishoyHanna Como coloco no meu formulário o anexo. Para os outros valores, o razor nos fornece uma sintaxe simples, mas como faço para esse arquivo?
Denis V #
1
oi, @ClintEastwood, esse post era para fazer upload de um arquivo, procurei online algo que correspondesse a vários uploads (para você) e encontrei aquele que acho que funcionaria. Novamente, seu modelo baseado que não está usando "Request.Files" stackoverflow.com/questions/36210413/…
Bishoy Hanna 11/16
17

Ver pagina

@using (Html.BeginForm("ActionmethodName", "ControllerName", FormMethod.Post, new { id = "formid" }))
 { 
   <input type="file" name="file" />
   <input type="submit" value="Upload" class="save" id="btnid" />
 }

Arquivo de script

$(document).on("click", "#btnid", function (event) {
        event.preventDefault();
        var fileOptions = {
            success: res,
            dataType: "json"
        }
        $("#formid").ajaxSubmit(fileOptions);
    });

No controlador

    [HttpPost]
    public ActionResult UploadFile(HttpPostedFileBase file)
    {

    }
Jagadisha BS
fonte
2
Concordo com @Muflix, você não precisa AJAXaqui. Html.BeginFormjá faz o trabalho. AJAX só é necessário se você não quer um redirecionamento para o<form action=LINK>
JAC
1
O Ajax é melhor para arquivos maiores, pois permite melhorar a experiência do usuário.
markthewizard1234
6

você só precisa alterar o nome da sua entrada arquivada porque o mesmo nome é necessário no parâmetro e o nome do campo de entrada apenas substitui esta linha Seu código está funcionando bem

 <input type="file" name="file" />
Muhammad Asad
fonte
2

Eu acho que, melhor maneira é usar HttpPostedFileBase em seu controlador ou API. Depois disso, você pode simplesmente detectar o tamanho, o tipo etc.

Propriedades do arquivo que você pode encontrar aqui:

MVC3 Como verificar se HttpPostedFileBase é uma imagem

Por exemplo ImageApi:

[HttpPost]
[Route("api/image")]  
public ActionResult Index(HttpPostedFileBase file)  
{  
    if (file != null && file.ContentLength > 0)  
        try 
        {  
            string path = Path.Combine(Server.MapPath("~/Images"),  
               Path.GetFileName(file.FileName));

            file.SaveAs(path);  
            ViewBag.Message = "Your message for success";  
        }  
        catch (Exception ex)  
        {  
            ViewBag.Message = "ERROR:" + ex.Message.ToString();  
        }  
    else 
    {  
        ViewBag.Message = "Please select file";  
    }  
    return View();  
}

Espero que ajude.

Petr Tomášek
fonte
Melhor que o que? O OP já está usando HttpPostedFileBase.
jpaugh