mare
mare

Reputation: 13083

Input file autobind to byte[] array in ASP.NET MVC

Anyone managed to get default binder to work with input file control and property of type byte array?

If I have a property on my ViewModel named Image and a file input control on my view name Image, default binder issue this error:

The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or a non-white space character among the padding characters.

Upvotes: 1

Views: 3552

Answers (2)

Yago Ferreira
Yago Ferreira

Reputation: 11

You should create a custom model binder that associates directly your uploaded file to a byte[] field in your model.

Example:

public class CustomByteArrayModelBinder : ByteArrayModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var file = controllerContext.HttpContext.Request.Files[bindingContext.ModelName];

        if (file != null)
        {
            if (file.ContentLength > 0)
            {
                var fileBytes = new byte[file.ContentLength];
                file.InputStream.Read(fileBytes, 0, fileBytes.Length);
                return fileBytes;
            }

            return null;
        }

        return base.BindModel(controllerContext, bindingContext);
    }
}

You also have to remove the default model binder, and add yours (in Global.asax.cs, inside the Application_Start method):

ModelBinders.Binders.Remove(typeof(byte[]));
ModelBinders.Binders.Add(typeof(byte[]), new CustomByteArrayModelBinder());

This code were retired from this good article: http://prideparrot.com/blog/archive/2012/6/model_binding_posted_file_to_byte_array

Best regards :)

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

Why do you need a byte[] array? The default model binder works with HttpPostedFileBase:

<% using (Html.BeginForm("upload", "home", FormMethod.Post, new { enctype = "multipart/form-data" })) { %>
    <input type="file" name="file" id="file" />
    <input type="submit" value="Upload" />
<% } %>

And the controller action that will handle this:

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

This works also with multiple files. You simply use IEnumerable<HttpPostedFileBase> in the signature of the action method.

Upvotes: 3

Related Questions