Uploading Images

9

I'm trying to upload images to my application. I did a prototype of upload, only it does not show the image, but the ID or NAME of it. And I'm uploading to a folder I've created in my project.

My questions are:

How do I show this image?

In the project I'm really working on, I need to show this image to the user because it's a school and needs to have the student's picture. I even created the student's registration;

How do I link this photo to the student's record?

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

And what is the best way to upload, by recording the image in the bank or in 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; }
}

ImageController.cs (Controller, and here only has the part of create)

  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 (Another 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>
}
    
asked by anonymous 29.04.2014 / 15:27

2 answers

10

Simple Solution:

So I figured out if you're using Entity Framework , great choice. So I made a very simple example of how 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; }
    }
}

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

Student controller

Create method

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

Firstly, I write the Student and the Photo comes logically blank (NULL) and there I check if the file that comes from the input type file comes with the image if it comes I extract from the file the extension of the same and generate a combination of AlunoId + '.' + Extensão da Foto being as example of name: 1.jpg (Student 1 and photo with extension jpg). I particularly use this technique so the photos do not overlap each other.

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

Student Views

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

The same way 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

Photo Display

@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>
    
29.04.2014 / 16:17
1

I usually save the image to a folder (in the project, or out of it), and save only the name of the image 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 image table). You can also save the name of the image in the user's table (just in case you associate only one photo), with only one table.

To present the image at the end of loading, you can use an extension or create your own using javascript. I have this link saved, try to sneak in.

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

EDIT

Save Document / Photo in the database and in a 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);
    
29.04.2014 / 15:39