Image Upload

Asked

Viewed 6,651 times

9

I am trying to upload images to my application. I have made a prototype upload, but it does not show the image, but its ID or NAME. And I’m uploading it to a folder I created in my project.

My doubts are:

How do I show this image?

In the project that I am working on, I need to show this image to the user, because it is a school and needs to have the student’s photo. I’ve even created the student register;

How to link this photo to the registration of the student in question?

Should I create a student model and another image model, or has some other form?

And what is the best way to upload, saving the image to the bank or to a folder in the project?

Here are my prototype codes:

Image.Cs (Model)

public partial class Imagem
{

    public int ID { get; set; }
    public string ImagePath { get; set; }
}

Imagemcontroller.Cs(Controller, and here only the create part)

  public ActionResult Create()
    {
        return View();
    }

    // POST: /Imagem/Create
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Imagem img, HttpPostedFileBase file)
    {
        if (ModelState.IsValid)
        {
            if (file != null)
            {
                file.SaveAs(HttpContext.Server.MapPath("~/Imagens/")
                                                      + file.FileName);
                img.ImagePath = file.FileName;
            }
            db.Imagems.Add(img);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(img);
    }

Index.cshtml(a View)

<table>
<tr>
    <th>
        @Html.DisplayNameFor(model => model.ImagePath)
    </th>
</tr>

@foreach (var item in Model) {
    <tr>
        <td>
           @Html.DisplayFor(modelItem => item.ID)
           @* <img src="@Url." alt="Image" width="300px" /> *@
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new {id = item.ID})
        </td>
    </tr>
  }
</table>

Create.cshtml(Other View)

@using (Html.BeginForm("Create", "Imagem", null, FormMethod.Post,
                          new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
    <legend>Image</legend>
    <div class="editor-label">
        @Html.LabelFor(model => model.ImagePath)
    </div>
    <div class="editor-field">
        <input id="ImagePath" title="Upload a product image"
               type="file" name="file" />
    </div>
    <p><input type="submit" value="Create" /></p>
</fieldset>
}

2 answers

10


Simple Solution:

From what I could tell Entity Framework, great choice. So I made a very simple example of what this behavior should be.

class Student

namespace MvcAppUpload.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class Aluno
    {
        public int AlunoId { get; set; }
        public string NomeCompleto { get; set; }
        public string Foto { get; set; }
    }
}

Notice that it is a simple class where you have a AlunoId which is the chave primária, NomeCompleto and Foto, and I always keep the path of the photo and the file inside the directory.

student controller

Metodo Create

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Aluno aluno, HttpPostedFileBase file)
{
    if (ModelState.IsValid)
    {
        db.Aluno.Add(aluno);
        db.SaveChanges();

        if (file != null)
        {
            String[] strName = file.FileName.Split('.');
            String strExt = strName[strName.Count() - 1];
            string pathSave = String.Format("{0}{1}.{2}", Server.MapPath("~/Imagens/"), aluno.AlunoId, strExt);
            String pathBase = String.Format("/Imagens/{0}.{1}", aluno.AlunoId, strExt);
            file.SaveAs(pathSave);
            aluno.Foto = pathBase;
            db.SaveChanges();
        }

        return RedirectToAction("Index");
    }

    return View(aluno);
}

First, I record the Student and the Photo comes logically in white (NULL) and then check if the file that comes from input type file comes with the image if it comes I extract from that file the extension of the same and Gero a combination of AlunoId + '.' + Extensão da Foto as an example of a name: 1.jpg (Student 1 and photo with jpg extension). I particularly use this technique so that photos do not overwrite each other.

Metodo Edit

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Aluno aluno, HttpPostedFileBase file)
{
    if (ModelState.IsValid)
    {
        db.Entry(aluno).State = EntityState.Modified;
        db.SaveChanges();
        if (file != null)
        {
             if (aluno.Foto != null)
             {
                if (System.IO.File.Exists(Server.MapPath("~/" + aluno.Foto)))
                {
                    System.IO.File.Delete(Server.MapPath("~/" + aluno.Foto));
                }
             }
            String[] strName = file.FileName.Split('.');
            String strExt = strName[strName.Count() - 1];
            string pathSave = String.Format("{0}{1}.{2}", Server.MapPath("~/Imagens/"), aluno.AlunoId, strExt);
            String pathBase = String.Format("/Imagens/{0}.{1}", aluno.AlunoId, strExt);
            file.SaveAs(pathSave);
            aluno.Foto = pathBase;
            db.SaveChanges();
        }
        return RedirectToAction("Index");
    }
    return View(aluno);
}

Views Aluno

View Create

@model MvcAppUpload.Models.Aluno
@{
    ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm("Create", "Alunos", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Aluno</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.NomeCompleto)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.NomeCompleto)
            @Html.ValidationMessageFor(model => model.NomeCompleto)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Foto)
        </div>
        <div class="editor-field">
            <input type="file" name="file" id="file" />
            @Html.HiddenFor(model => model.Foto)
            @Html.ValidationMessageFor(model => model.Foto)
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Follows the same form for Edit.

View Edit

@model MvcAppUpload.Models.Aluno
@{
    ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm("Edit", "Alunos", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Aluno</legend>
        @Html.HiddenFor(model => model.AlunoId)
        <div class="editor-label">
            @Html.LabelFor(model => model.NomeCompleto)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.NomeCompleto)
            @Html.ValidationMessageFor(model => model.NomeCompleto)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Foto)
        </div>
        <div class="editor-field">
            <input type="file" name="file" id="file" />
            @Html.HiddenFor(model => model.Foto)            
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

View Index

Exhibition of the Photo

@model IEnumerable<MvcAppUpload.Models.Aluno>
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.NomeCompleto)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Foto)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.NomeCompleto)
        </td>
        <td>
            <img src="@item.Foto" border="0" width="150px" />
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.AlunoId }) |
            @Html.ActionLink("Details", "Details", new { id=item.AlunoId }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.AlunoId })
        </td>
    </tr>
}
</table>
  • Really good guy, really good. But in this case, I would need to have in the controller the Delete, Update and Details ? I mean, if the user wants to change the image, he would change it in a good way ?

  • Yes, I would change in a good way, the example is for you to have idea with would be a create and Edit, but, the other methods are not mandatory

  • Oh I got it. So Create and Edit would be the same way you put it there ? Because I’m afraid the directory is too full of images. I mean, the user only creates one on top of the other, never deletes the old photo.

  • You can delete the old photo yes on Edit... but if the names match it overwrites the last photo from that record

  • I get it, and if the name is the same, he keeps the two photos ? The old and the new right ?

  • 1

    I changed the code to delete if Edit comes with photo!

  • 1

    Thank you so much for your patience and for your willingness to help me. Look worked right, the way I wanted. I wanted to thank you so much ! Thanks for the help @Fccdias!

  • The file is doing what in the code is that here gives me error

Show 3 more comments

1

I usually store the image in a folder (in the project, or outside it), and only save the image name in the database.

Now if you want to associate the image with the User, they need to have a relation between the tables (or save the image id in the user table, or the user id in the images table). You can also save the image name in the user’s table (just in case you associate only one photo), with only one table.

To display the image immediately after loading, you can use an extension or create it yourself using javascript. I have this link guarded, try to take a peek.

PS- I tried to comment, but it was too big :P

EDIT

Save Document/Photo to database and folder:

//Guardar nome do ficheiro na tabela/inserir user
TabelaUtilizador df = new TabelaUtilizador();
df.Nome = "Alberto Silva" //Nome do User
df.NomeDocFoto = nameFile; // ESTE namefile é o nome do teu ficheiro, que deves receber por parametro na função
db.TabelaUtilizador.Add(df);
db.SaveChanges();
//Guardar Ficheiro
var path = Path.Combine(("D:/PastaFotosUser"), nameFile); // para pastas fisicas
filepath.SaveAs(path);
  • Thank you so much for your help. But for example, this link you sent me is for uploading files, it works the same way for photos ? I say, upload and display and such ? And something else, tranquil have put in response ! @Cesarmiguel

  • Yes, you can test here http://blueimp.github.io/jQuery-File-Upload/

  • I have another question, how would I save the image in a folder and its name in the database ? Thus getting all the data in a table ?

  • 1

    I changed my answer

  • Yes yes, so create and Edit are the same thing right? I would only use Edit in the controller to upload the photo, right ?

  • Yes it’s the same thing, the Edit I have upstairs is saying I edited the answer. Don’t call

  • Aah ta ! Thank you very much, dear, for your help and patience !

  • That’s what we’re here for :)

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.