asp.net mvc - HTML Helper for <input type="file" />

original title: "asp.net mvc - Html helper for <input type="file" />"


Translate

Is there a HTMLHelper for file upload? Specifically, I am looking for a replace of

<input type="file"/>

using ASP.NET MVC HTMLHelper.

Or, If I use

using (Html.BeginForm()) 

What is the HTML control for the file upload?



有用于文件上传的HTMLHelper吗?具体来说,我正在寻找替代<input type="file"/>使用ASP.NET MVC HTMLHelper。或者,如果我使用(Html.BeginForm()),那是什么...

这是翻译后的摘要,如果您需要查看完整的翻译,请单击“Translate”图标


所有的回答
  • Translate

    HTML Upload File ASP MVC 3.

    Model: (Note that FileExtensionsAttribute is available in MvcFutures. It will validate file extensions client side and server side.)

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

    HTML View:

    @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)
    }
    

    Controller action:

    [HttpPost]
    public ActionResult Action(ViewModel model)
    {
        if (ModelState.IsValid)
        {
            // Use your file here
            using (MemoryStream memoryStream = new MemoryStream())
            {
                model.File.InputStream.CopyTo(memoryStream);
            }
        }
    }
    

  • Translate

    You can also use:

    @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> 
    }
    

  • Translate

    I had this same question a while back and came across one of Scott Hanselman's posts:

    Implementing HTTP File Upload with ASP.NET MVC including Tests and Mocks

    Hope this helps.


  • Translate

    Or you could do it properly:

    In your HtmlHelper Extension class:

    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));
        }
    

    This line:

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

    Generates an id unique to the model, you know in lists and stuff. model[0].Name etc.

    Create the correct property in the model:

    public HttpPostedFileBase NewFile { get; set; }
    

    Then you need to make sure your form will send files:

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

    Then here's your helper:

    @Html.FileFor(x => x.NewFile)
    

  • Translate

    Improved version of Paulius Zaliaduonis' answer:

    In order to make the validation work properly I had to change the Model to:

    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;
                }
            }
    }
    

    and the view to:

    @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)
    }
    

    This is required because what @Serj Sagan wrote about FileExtension attribute working only with strings.


  • Translate

    To use BeginForm, here's the way to use it:

     using(Html.BeginForm("uploadfiles", 
    "home", FormMethod.POST, new Dictionary<string, object>(){{"type", "file"}})
    

  • Translate

    This also works:

    Model:

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

    View:

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

    Controller action:

    [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;
                }
    

    List of contentTypes


  • Translate

    This is a little hacky I guess, but it results in the correct validation attributes etc being applied

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