0

I have the following action in my ImagesController:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ImageID,ImageCaption,ImageFile")] Image image)
{
    if (ModelState.IsValid)
    {
        HttpPostedFileBase uploadedImage = Request.Files[0];

        if (uploadedImage != null && uploadedImage.ContentLength > 0)
        {
            // Determining file size.
            int FileSize = uploadedImage.ContentLength;

            // Creating a byte array corresponding to file size.
            byte[] FileByteArray = new byte[FileSize];

            // Posted file is being pushed into byte array.
            uploadedImage.InputStream.Read(FileByteArray, 0, FileSize);

            // Assigning byte array to model property
            image.ImageFile = FileByteArray;
        }

        db.Images.Add(image);
        db.SaveChanges();

        return RedirectToAction("Index");
    }

    return View(image);
}

This is my Image model:

public class Image
{
        public int ImageID { get; set; }
        [Display(Name="Caption")]
        public string ImageCaption { get; set; }
        [Display(Name = "Image")]
        public byte[] ImageFile { get; set; }
        public virtual ApplicationUser ApplicationUser { get; set; }
    }

And this is my view that accepts an image/file upload:

@using (Html.BeginForm("Create", "Images", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Image</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.ImageCaption, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ImageCaption, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.ImageCaption, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ImageFile, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.ImageFile, new { type = "file" })
                @Html.ValidationMessageFor(model => model.ImageFile, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

I am trying to save an image uploaded by a user. However, every time I try to upload a file I get 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 an illegal character among the padding characters.

The code in my controller should convert the uploaded file into byte array then assign that array to my ImageFile model property. The code below ModelState.IsValid and above db.Images.Add(image) in my controller doesn't seem to be working.

Questions:

  • Is FileByteArray assigned to my model property correctly?
  • Is my form/view correct?
  • Why do I keep getting the error?
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Bonga
  • 97
  • 11
  • 1
    When you say "uploaded file", it looks from your code that you expect the user to paste a Base64 encoded string that represents an image file into a textbox. Is that really what you want to do? – Ben Robinson Sep 08 '15 at 15:26
  • If you are referring to `@Html.TextBoxFor(model => model.ImageFile, new { type = "file" })` found in my view, this renders an upload button (which works fine), not a text box. Is it wrong? If so, which html helper should I then use? – Bonga Sep 08 '15 at 16:45
  • You cant assign a value to a file input (it would be a major security issue). Bit unclear what you really trying to do here. –  Sep 09 '15 at 00:11
  • All I am trying do is to save an image uploaded by a user into a database in byte format. From my understanding, this is the only format in which I can store an image into a database. I thought the code in my controller would convert the uploaded image into byte format so that I can save it in my `ImageFile` model property. If I remove the code below `ModelState.IsValid` and above `db.Images.Add(image)` in my controller, I get the same error as if that code has no effect at all. How would one implement this? – Bonga Sep 09 '15 at 05:40
  • You can save your file as your doing now (although its not recommend to store files in a database and it would be better to use a file system and just save the path in the database). Your issue is that you cannot use `@Html.TextBoxFor(m=> m.ImageFile, new { type = "file" })` because you cannot set the value of a file input. If you want to bind to a property, then the property needs to be `public HttpPostedFileBase ImageFile { get; set; }`. If you need to return the view because `ModelState` is invalid, then the user needs to select the file again. –  Sep 09 '15 at 10:41
  • That makes sense. Just out of curiosity, why is it not recommended to store files in a database? – Bonga Sep 10 '15 at 07:54
  • It depends a bit on exactly what you want to store and how often t will be accessed. There is plenty of discussion on SO about this - e.g [this one](http://stackoverflow.com/questions/3748/storing-images-in-db-yea-or-nay#3756) –  Sep 10 '15 at 08:28

0 Answers0