Oggie Oggie - 3 months ago 11
ASP.NET (C#) Question

ASP.NET MVC - How to upload an image and save URL in the database

I would appreciate if anyone could help me with this. I have input file control in a form in a view and when someone picks a picture and clicks the submit button on the form, that file has to be saved in /Pictures folder in the application and file path needs to be saved in SQL database as string (like: /Pictures/filename).

Models class part:

[Table("Automobil")]
public partial class Automobil
{ .....
[Required]
[StringLength(30)]
public string Fotografija{ get; set; }
......


View (Create) file part:

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

....
<div class="form-group">
<div class="editor-field">
@Html.TextBoxFor(model => model.Fotografija, new { type = "file" })
@Html.ValidationMessageFor(model => model.Fotografija, "", new { @class = "text-danger" })
</div>
</div>
....


Controller part:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "AutomobilID,Marka,Model,Godiste,Zapremina_motora,Snaga,Gorivo,Karoserija,Fotografija,Opis,Cena,Kontakt")] Automobil automobil)
{
if (ModelState.IsValid)
{
db.Automobils.Add(automobil);
db.SaveChanges();
return RedirectToAction("Index");
}

return View(automobil);
}


What do I need to do so the photo(Fotografija) could be saved in the application folder Pictures, and file path in SQL base (like /Pictures/filename)?

Thank you in advance for helping the beginner.

Answer

Looks like your Fotografija property is string type where you want to save the unique file name. You do not want to use that field to get the file from the browser. Let's use another input field for that.

@using (Html.BeginForm("Index", "Home", FormMethod.Post, 
                                                   new { enctype = "multipart/form-data" }))
{
  <div class="form-group">
        <div class="editor-field">
            @Html.TextBoxFor(model => model.Model)
            @Html.ValidationMessageFor(model => model.Model)
        </div>
    </div>
    <!-- TO DO : Add other form fields also -->

    <div class="form-group">
        <div class="editor-field">
           <input type="file" name="productImg" />
        </div>
    </div>
    <input type="submit" />
}

Now update your HttpPost action method to have one more parameter of type HttpPostedFileBase. The name of this parameter should be same as the input file field name we added (productImg)

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "AutomobilID,Marka,Model,Godiste,
          Zapremina_motora,Snaga,Gorivo,Karoserija,Opis,Cena,Kontakt")] Automobil automobil, 
                                           HttpPostedFileBase productImg)
{
    if (ModelState.IsValid)
    {
        if(productImg!=null)
        {
          var fileName = Path.GetFileName(productImg.FileName);
          var directoryToSave = Server.MapPath(Url.Content("~/Pictures"));

           var pathToSave = Path.Combine(directoryToSave, fileName);
           productImg.SaveAs(pathToSave);
           automobil.Fotografija= fileName;
        } 

        db.Automobils.Add(automobil);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(automobil);
}

You have to remove any validation data annotation decoration(Ex : [Required], [MinLength] etc) on the Fotografija field.

I also strongly suggest you to update the fileName before saving to be a unique one to avoid collision/overwriting of existing files. You can add the DateTime current value to the file name (Before the extension) to make it unique