عملیات CRUD با امکان فایل آپلود چندگانه در MVC

در این مقاله به همراه یک Sample که در آن کاربر امکان آپلود کردن چندین فایل (هر نوع فایلی) را دارد ، ایجاد خواهیم کرد.چهار عمل اصلی دستکاری داده را نیز پیاده سازی خواهیم کرد.

عملیات CRUD با امکان فایل آپلود چندگانه در  MVC

آکادمی برنامه نویسان ، برگزار کننده دوره های آموزش برنامه نویسی با استفاده از اساتید مجرب و حرفه ای در سراسر ایران .

[ جهت مشاهده دوره های درحال ثبت نام کلیک کنید ]

ارائه مدارک معتبر آموزشی و ورود به بازار کار .

برای ساخت پروژه مراحل زیر را انجام دهید.
1 – یک پروژه Empty در ASP.NET MVC 5 باز کنید و در پایین تیک MVC را بزنید
2- بعد از ایجاد پروژه در داخل دیتابیس یک دیتابیس ساده با دوجدول با فیلد هایی به شرح زیرو Relation بین آنها ایجاد کنید



3-بر روی پوشه Model خود کلیک کنید و Add->New Item->data->ADO.net Entity را انتخاب کنید و سپس به دیتابیس Upload که در مرحله قبل ایجاد کردید وصل شوید.
4- در داخل Web.config رشته اتصال به صورت زیر اضافه شده است

 <connectionStrings>
    <add name="UploadEntities" connectionString="metadata=res://*/Models.Model1.csdl|res://*/Models.Model1.ssdl|res://*/Models.Model1.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=Upload;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
    <add name="UploadEntities1" connectionString="metadata=res://*/Models.Model1.csdl|res://*/Models.Model1.ssdl|res://*/Models.Model1.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=Upload;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>


5- برای نصب EntityFramework در داخل این پروژه در داخل Tools->Option->Nuget Consol Package Manager دستور زیر را تایپ کنید

Install-Package EntityFramework

مدل شما باید شبیه شکل زیر باشد

در مسیر Models folder > Add > Class رفته و یک کلاس با کدهای زیر به پروژه اضافه می کنیم

public class Support
   {
       public int SupportId { get; set; }
 
       [Required(ErrorMessage = "Please Enter Your Name")]
       [Display(Name = "Name")]
       [MaxLength(100)]
       public string Name { get; set; }
 
       [Required(ErrorMessage = "Please Enter Summary")]
       [Display(Name = "Summary")]
       [MaxLength(500)]
       public string Summary { get; set; }
 
       public virtual ICollection<FileDetail> FileDetails { get; set; }
 
   }


در شکل زیر نحوه ارتباط اجزای برنامه و جریان کار آورده شده است

به صورت ساده وقتی کاربر فایلی را انتخاب می کند این فایل در داخل برنامه و در داخل app_data->Upload ذخیره می شود ولی در داخل بانک تنها نام این فایل که آپلود شده است را ذخیره می کنیم
کد هایی که در داخل فایل Layout.cshtml قرار دارد به صورت زیر است

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="~/Scripts/modernizr-2.6.2.js"></script>
</head>
<body dir="rtl" style="background-color:khaki">
    @RenderBody()

<footer>
    <h2><a href="http://www.barnamenevisan.org">برنامه نویسان :مرجع تخصصی برنامه نویسان</a></h2>
    
</footer>
   

    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
    @RenderSection("scripts", required: false)
</body>
</html>


5- بر روی فولدر کنترلر کلیک راست کرده و یک کنترلر خالی به پروژه اضافه می کنیم
در داخل کنترلر چهار عمل اصلی دستکاری داده یا همان CRUD را به صورت زیر می نویسیم

 public class SupportController : Controller
    {
        //private SupportContext db = new SupportContext();
        private UploadEntities1 db = new UploadEntities1();

        //
        // GET: /Support/

        public ActionResult Index()
        {
            return View(db.Supports.ToList());
        }

        //
        // GET: /Support/Create

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

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(Support support)
        {
            if (ModelState.IsValid)
            {
                List<FileDetail> fileDetails = new List<FileDetail>();
                for (int i = 0; i < Request.Files.Count; i++)
                {
                    var file = Request.Files[i];

                    if (file != null && file.ContentLength > 0)
                    {
                        var fileName = Path.GetFileName(file.FileName);
                        FileDetail fileDetail = new FileDetail()
                        {
                            FileName = fileName,
                            Extension = Path.GetExtension(fileName),
                            
                        };
                        fileDetails.Add(fileDetail);

                        var path = Path.Combine(Server.MapPath("~/App_Data/Upload/"), fileDetail.id + fileDetail.Extension);
                        file.SaveAs(path);
                    }
                }

                support.FileDetails = fileDetails;
                db.Supports.Add(support);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(support);
        }

        //
        // GET: /Support/Edit/5

        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Support support = db.Supports.Include(s => s.FileDetails).SingleOrDefault(x => x.SupportId == id);
            if (support == null)
            {
                return HttpNotFound();
            }
            return View(support);
        }


        public FileResult Download(String p, String d)
        {
            return File(Path.Combine(Server.MapPath("~/App_Data/Upload/"), p), System.Net.Mime.MediaTypeNames.Application.Octet, d);
        }



        //
        // POST: /Support/Edit/5

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(Support support)
        {
            if (ModelState.IsValid)
            {

                //New Files
                for (int i = 0; i < Request.Files.Count; i++)
                {
                    var file = Request.Files[i];

                    if (file != null && file.ContentLength > 0)
                    {
                        var fileName = Path.GetFileName(file.FileName);
                        FileDetail fileDetail = new FileDetail()
                        {
                            FileName = fileName,
                            Extension = Path.GetExtension(fileName),
                         ////////////////////
                            SupportId = support.SupportId
                        };
                        var path = Path.Combine(Server.MapPath("~/App_Data/Upload/"), fileDetail.id + fileDetail.Extension);
                        file.SaveAs(path);

                        db.Entry(fileDetail).State = EntityState.Added;
                    }
                }

                db.Entry(support).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(support);
        }



        [HttpPost]
        public JsonResult DeleteFile(string id)
        {
            if (String.IsNullOrEmpty(id))
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return Json(new { Result = "Error" });
            }
            try
            {
                Guid guid = new Guid(id);
                FileDetail fileDetail = db.FileDetails.Find(guid);
                if (fileDetail == null)
                {
                    Response.StatusCode = (int)HttpStatusCode.NotFound;
                    return Json(new { Result = "Error" });
                }

                //Remove from database
                db.FileDetails.Remove(fileDetail);
                db.SaveChanges();

                //Delete file from the file system
                var path = Path.Combine(Server.MapPath("~/App_Data/Upload/"), fileDetail.id + fileDetail.Extension);
                if (System.IO.File.Exists(path))
                {
                    System.IO.File.Delete(path);
                }
                return Json(new { Result = "OK" });
            }
            catch (Exception ex)
            {
                return Json(new { Result = "ERROR", Message = ex.Message });
            }
        }
    //
        // POST: /Support/Delete/5

        [HttpPost]
        public JsonResult Delete(int id)
        {
            try
            {
                Support support = db.Supports.Find(id);
                if (support == null)
                {
                    Response.StatusCode = (int)HttpStatusCode.NotFound;
                    return Json(new { Result = "Error" });
                }

                //delete files from the file system

                foreach (var item in support.FileDetails){
                    String path = Path.Combine(Server.MapPath("~/App_Data/Upload/"), item.id + item.Extension);
                    if (System.IO.File.Exists(path))
                    {
                        System.IO.File.Delete(path);
                    }
                }

                db.Supports.Remove(support);
                db.SaveChanges();
                return Json(new { Result = "OK" });
            }
            catch (Exception ex)
            {
                return Json(new { Result = "ERROR", Message = ex.Message });
            }
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }


View مربوط به هر کدام از اکشن های چهار گانه به صورت زیر است
View مربوط به ایجاد که در آن اطلاعاتی که کاربر آپلود کرده است در داخل بانک ذخیره می شود به صورت زیر است

@model MultipleFileUpload.Models.Support
@{
    ViewBag.Title = "Create";
}
@using (Html.BeginForm("Create", "Support", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Create Support Request</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Summary)
        </div>
        <div class="editor-field">
            @Html.TextAreaFor(model => model.Summary)
            @Html.ValidationMessageFor(model => model.Summary)
        </div>
        <div class="editor-label">
          <label>Files:</label>
        </div>
        <div class="editor-field">
            <input type="file" name="file" multiple="multiple" />
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
}

view مربوط به ویرایش به صورت زیر است :

@model MultipleFileUpload.Models.Support
@{
    ViewBag.Title = "Edit";
}
@using (Html.BeginForm("Edit", "Support", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Edit Support Request</legend>

        @Html.HiddenFor(model => model.SupportId)

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Summary)
        </div>
        <div class="editor-field">
            @Html.TextAreaFor(model => model.Summary)
            @Html.ValidationMessageFor(model => model.Summary)
        </div>
        <div class="editor-label">
           <label>Files:</label>
        </div>
        <div class="editor-field">
            <input type="file" name="file" multiple="multiple" />

            <ul class="attachment">
                @foreach (var item in Model.FileDetails)
                {              
                    <li>
                        <a class="title" href="/Support/Download/?p=@(item.Id + item.Extension)&d=@item.FileName">@item.FileName</a>
                        <a href="javascript:void(0);" data-id="@item.Id" class="deleteItem">X</a>
                    </li>            
                }
            </ul>
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

    <script>
        $('.deleteItem').click(function (e) {
            e.preventDefault();
            var $ctrl = $(this);
            if (confirm('Do you really want to delete this file?')) {
                $.ajax({
                    url: '@Url.Action("DeleteFile")',
                    type: 'POST',
                    data: { id: $(this).data('id') }
                }).done(function (data) {                  
                    if (data.Result == "OK") {
                        $ctrl.closest('li').remove();                        
                    }
                    else if (data.Result.Message) {
                        alert(data.Result.Message);
                    }
                }).fail(function () {
                    alert("There is something wrong. Please try again.");
                })

            }
        });
    </script>

بعد از اجرای برنامه شکل زیر را خواهید دید

فایل های ضمیمه
دانلود نسخه ی PDF این مطلب