Ayudante HTML para <input type = "file" />

124

¿Hay una HTMLHelperpara subir archivos? Específicamente, estoy buscando un reemplazo de

<input type="file"/>

usando ASP.NET MVC HTMLHelper.

O si uso

using (Html.BeginForm()) 

¿Cuál es el control HTML para la carga de archivos?

Graviton
fuente

Respuestas:

207

Archivo de carga HTML ASP MVC 3.

Modelo : ( Tenga en cuenta que FileExtensionsAttribute está disponible en MvcFutures. Validará las extensiones de archivo del lado del cliente y del lado del servidor ) .

public class ViewModel
{
    [Required, Microsoft.Web.Mvc.FileExtensions(Extensions = "csv", 
             ErrorMessage = "Specify a CSV file. (Comma-separated values)")]
    public HttpPostedFileBase File { get; set; }
}

Vista HTML :

@using (Html.BeginForm("Action", "Controller", FormMethod.Post, new 
                                       { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.File, new { type = "file" })
    @Html.ValidationMessageFor(m => m.File)
}

Acción del controlador :

[HttpPost]
public ActionResult Action(ViewModel model)
{
    if (ModelState.IsValid)
    {
        // Use your file here
        using (MemoryStream memoryStream = new MemoryStream())
        {
            model.File.InputStream.CopyTo(memoryStream);
        }
    }
}
Paulius Zaliaduonis
fuente
Esto no representa una entrada de archivo <input type="file" />, solo un cuadro de texto
Ben
@PauliusZaliaduonis con la línea Microsoft.Web.Mvc.FileExtensions, el MVC está subrayado en rojo. ¿Cómo arreglo eso?
Pomster
1
@pommy Tenga en cuenta que FileExtensionsAttribute está disponible en MvcFutures (a partir de MVC3). Puede usar fuentes desde aquí: Fuentes o está disponible en .NET Framework 4.5, consulte la documentación de MSDN
Paulius Zaliaduonis
1
Desafortunadamente, el atributo FileExtension no parece funcionar con el tipo de propiedades HttpPostedFileBase, sino que solo parece una cadena. Al menos nunca aceptó pdf como una extensión válida.
Serj Sagan
Esto agregará un atributo de valor (value = "") que no se valida como HTML5 válido. El valor no es válido en los tipos de entrada de archivo e imagen. No veo ninguna forma de eliminar el atributo de valor. Parece estar codificado.
Dan Friedman
19

También puedes usar:

@using (Html.BeginForm("Upload", "File", FormMethod.Post, new { enctype = "multipart/form-data" }))
{ 
    <p>
        <input type="file" id="fileUpload" name="fileUpload" size="23" />
    </p>
    <p>
        <input type="submit" value="Upload file" /></p> 
}
balexandre
fuente
6

O podrías hacerlo correctamente:

En su clase de extensión HtmlHelper:

public static MvcHtmlString FileFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
    {
        return helper.FileFor(expression, null);
    }

public static MvcHtmlString FileFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        var builder = new TagBuilder("input");

        var id = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(expression));
        builder.GenerateId(id);
        builder.MergeAttribute("name", id);
        builder.MergeAttribute("type", "file");

        builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));

        // Render tag
        return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
    }

Esta línea:

var id = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(expression));

Genera una identificación única para el modelo, ya sabes en listas y otras cosas. modelo [0] .Nombre, etc.

Cree la propiedad correcta en el modelo:

public HttpPostedFileBase NewFile { get; set; }

Luego debe asegurarse de que su formulario envíe archivos:

@using (Html.BeginForm("Action", "Controller", FormMethod.Post, new { enctype = "multipart/form-data" }))

Entonces aquí está tu ayudante:

@Html.FileFor(x => x.NewFile)
Tod
fuente
Esta solución es más atractiva y me mantiene consistente con los métodos de ayuda @Html.
Yahfoufi
4

Versión mejorada de la respuesta de Paulius Zaliaduonis:

Para que la validación funcione correctamente, tuve que cambiar el Modelo a:

public class ViewModel
{
      public HttpPostedFileBase File { get; set; }

        [Required(ErrorMessage="A header image is required"), FileExtensions(ErrorMessage = "Please upload an image file.")]
        public string FileName
        {
            get
            {
                if (File != null)
                    return File.FileName;
                else
                    return String.Empty;
            }
        }
}

y la vista a:

@using (Html.BeginForm("Action", "Controller", FormMethod.Post, new 
                                       { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.File, new { type = "file" })
    @Html.ValidationMessageFor(m => m.FileName)
}

Esto es necesario porque lo que escribió @Serj Sagan sobre el atributo FileExtension funciona solo con cadenas.

BornToCode
fuente
¿No puedes combinar esta respuesta con la respuesta de Paulius?
Graviton
2

Para usar BeginForm, esta es la forma de usarlo:

 using(Html.BeginForm("uploadfiles", 
"home", FormMethod.POST, new Dictionary<string, object>(){{"type", "file"}})
Graviton
fuente
2
Primero, ¿cómo generar un elemento de entrada y ahora habla de cómo generar un elemento de formulario? ¿Es esta realmente tu respuesta?
pupeno
0

Esto también funciona:

Modelo:

public class ViewModel
{         
    public HttpPostedFileBase File{ get; set; }
}

Ver:

@using (Html.BeginForm("Action", "Controller", FormMethod.Post, new 
                                       { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.File, new { type = "file" })       
}

Acción del controlador:

[HttpPost]
public ActionResult Action(ViewModel model)
{
    if (ModelState.IsValid)
    {
        var postedFile = Request.Files["File"];

       // now you can get and validate the file type:
        var isFileSupported= IsFileSupported(postedFile);

    }
}

public bool IsFileSupported(HttpPostedFileBase file)
            {
                var isSupported = false;

                switch (file.ContentType)
                {

                    case ("image/gif"):
                        isSupported = true;
                        break;

                    case ("image/jpeg"):
                        isSupported = true;
                        break;

                    case ("image/png"):
                        isSupported = true;
                        break;


                    case ("audio/mp3"):  
                        isSupported = true;
                        break;

                    case ("audio/wav"):  
                        isSupported = true;
                        break;                                 
                }

                return isSupported;
            }

Lista de tipos de contenido

Eyal
fuente
-2

Esto es un poco hacky, supongo, pero da como resultado que se apliquen los atributos de validación correctos, etc.

@Html.Raw(Html.TextBoxFor(m => m.File).ToHtmlString().Replace("type=\"text\"", "type=\"file\""))
Luke Schafer
fuente