ASP.NET MVC
雖然現在檔案上傳下載網路上有很多範例,但範例很陽春…這一次筆者要將這些功能整合起來,這些功能在內部系統或後台系統實用非常高,也是實際上最常見需求,本例子用非常簡易方式來陳現。
這樣不用老是遇到問題,就去問google老大,成品會如下…
這一次就從新的專案MVC 5開始進行開發這一整個檔案管理系統機制、這個功能已經具備CRUD以外,包含了檔案的上傳、下載、刪除的機制。
Model分別有兩個Class,一個是Person和AppendFile
public class Person
{
public int Id { get; set; }
[Required(ErrorMessage = "請填寫姓名")]
[DisplayName("姓名")]
public string Name { get; set; }
[Required(ErrorMessage = "請填寫備註")]
[DisplayName("備註")]
public string Remark { get; set; }
public virtual ICollection<AppendFile> AppendFiles { get; set; }
}
public class AppendFile
{
public Guid Id { get; set; }
public string FileName { get; set; }
public string Extension { get; set; }
public int PersonId { get; set; }
public virtual Person Person { get; set; }
}
上述是EF的一對多關聯設計。
public class PersonContext:DbContext
{
public PersonContext()
: base("name=DefaultConnection")
{
}
public DbSet<Person> Persons { get; set; }
public DbSet<AppendFile> AppendFiles { get; set; }
}
WebConfig底下
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=localhost;Initial Catalog=UploadFileDemo;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
最後開始進行做資料移轉
Enable-Migrations
Add-Migration InitCreateTable
Update-Database
先開始撈取資料和建立Controller並建立檢視
private PersonContext db = new PersonContext();
public ActionResult Index()
{
return View(db.Persons.ToList());
}
public ActionResult Create()
{
return View();
}
最後在Index中進行刻View畫面
@model IEnumerable<FileUpload.Models.Person>
@{ ViewBag.Title = "Index"; }
<h2>清單</h2>
<p>
@Html.ActionLink("新增", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Remark)
</th>
<th>附件數</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Remark)
</td>
<td>
@if (item.AppendFiles.Count() == 0)
{
<span>無檔案</span>
}
else
{
<span>@item.AppendFiles.Count() File(s)</span>
}
</td>
<td>
@Html.ActionLink("修改", "Edit", new { id = item.Id }) |
<a href="javascript:void(0);" data-id="@item.Id" class="deleteItem">刪除</a>
</td>
</tr>
}
</table>
@section Scripts {
<script>
</script>
}
@model FileUpload.Models.Person
@{ ViewBag.Title = "建立"; }
@using (Html.BeginForm("Create", "Home", null, FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>建立個人資料與附件</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.Remark)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.Remark)
@Html.ValidationMessageFor(model => model.Remark)
</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="儲存" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("回清單頁", "Index")
</div>
@section Scripts {
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
}
最後寫Create Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Person person)
{
if (ModelState.IsValid)
{
List<AppendFile> appendFiles = new List<AppendFile>();
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);
AppendFile appendFile = new AppendFile()
{
FileName = fileName,
Extension = Path.GetExtension(fileName),
Id = Guid.NewGuid()
};
appendFiles.Add(appendFile);
var folder = Server.MapPath("~/App_Data/Upload/");
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
var path = Path.Combine(folder, appendFile.Id + appendFile.Extension);
file.SaveAs(path);
}
}
person.AppendFiles = appendFiles;
db.Persons.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(person);
}
最後補上修改與刪除檔案、下載機制全貌,並加入修改的檢視處理
using FileUpload.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using System.Data.Entity;
namespace FileUpload.Controllers
{
public class HomeController : Controller
{
private PersonContext db = new PersonContext();
public ActionResult Index()
{
return View(db.Persons.ToList());
}
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Person person)
{
if (ModelState.IsValid)
{
List<AppendFile> appendFiles = new List<AppendFile>();
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);
AppendFile appendFile = new AppendFile()
{
FileName = fileName,
Extension = Path.GetExtension(fileName),
Id = Guid.NewGuid()
};
appendFiles.Add(appendFile);
var folder = Server.MapPath("~/App_Data/Upload/");
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
var path = Path.Combine(folder, appendFile.Id + appendFile.Extension);
file.SaveAs(path);
}
}
person.AppendFiles = appendFiles;
db.Persons.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(person);
}
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Person person = db.Persons.Include(p => p.AppendFiles).SingleOrDefault(x => x.Id == id);
if (person == null)
{
return HttpNotFound();
}
return View(person);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Person person)
{
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);
AppendFile appendFile = new AppendFile()
{
FileName = fileName,
Extension = Path.GetExtension(fileName),
Id = Guid.NewGuid()
};
var folder = Server.MapPath("~/App_Data/Upload/");
var path = Path.Combine(folder, appendFile.Id + appendFile.Extension);
file.SaveAs(path);
db.Entry(appendFile).State = EntityState.Added;
}
}
db.Entry(person).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(person);
}
[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);
var appendFile = db.AppendFiles.Find(guid);
if (appendFile == null)
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
return Json(new { Result = "Error" });
}
//Remove from database
db.AppendFiles.Remove(appendFile);
db.SaveChanges();
var folder = Server.MapPath("~/App_Data/Upload/");
//Delete file from the file system
var path = Path.Combine(folder, appendFile.Id + appendFile.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 });
}
}
[HttpPost]
public JsonResult Delete(int id)
{
try
{
Person person = db.Persons.Find(id);
if (person == null)
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
return Json(new { Result = "Error" });
}
//delete files from the file system
var folder = Server.MapPath("~/App_Data/Upload/");
foreach (var item in person.AppendFiles)
{
String path = Path.Combine(folder, item.Id + item.Extension);
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
}
db.Persons.Remove(person);
db.SaveChanges();
return Json(new { Result = "OK" });
}
catch (Exception ex)
{
return Json(new { Result = "ERROR", Message = ex.Message });
}
}
public FileResult Download(String p, String d)
{
return File(Path.Combine(Server.MapPath("~/App_Data/Upload/"), p), System.Net.Mime.MediaTypeNames.Application.Octet, d);
}
}
}
@model FileUpload.Models.Person
@{ ViewBag.Title = "Edit"; }
@using (Html.BeginForm("Edit", "Home", null, FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>修改資料</legend>
@Html.HiddenFor(model => model.Id)
<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.Remark)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.Remark)
@Html.ValidationMessageFor(model => model.Remark)
</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.AppendFiles)
{
<li>
<a class="title" href="/Home/Download/?p=@(item.Id + item.Extension)&d=@item.FileName">@item.FileName</a>
<a href="javascript:void(0);" data-id="@item.Id" class="deleteItem">刪除檔案</a>
</li>
}
</ul>
</div>
<p>
<input type="submit" value="儲存" />
</p>
</fieldset>}
<div>
@Html.ActionLink("回清單", "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('是否刪除此筆檔案?')) {
$.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 () {
})
}
});
</script>
}
最後回頭再補上首頁的刪除詢問項目
@model IEnumerable<FileUpload.Models.Person>
@{ ViewBag.Title = "Index"; }
<h2>清單</h2>
<p>
@Html.ActionLink("新增", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Remark)
</th>
<th>附件數</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Remark)
</td>
<td>
@if (item.AppendFiles.Count() == 0)
{
<span>無檔案</span>
}
else
{
<span>@item.AppendFiles.Count() File(s)</span>
}
</td>
<td>
@Html.ActionLink("修改", "Edit", new { id = item.Id }) |
<a href="javascript:void(0);" data-id="@item.Id" class="deleteItem">刪除</a>
</td>
</tr>
}
</table>
@section Scripts
{
<script>
$('.deleteItem').click(function (e) {
e.preventDefault();
var $ctrl = $(this);
if (confirm('確認要刪除該項目?')) {
$.ajax({
url: '@Url.Action("Delete")',
type: 'POST',
data: { id: $(this).data('id') }
}).done(function (data) {
if (data.Result == "OK") {
$ctrl.closest('tr').remove();
}
else if (data.Result.Message) {
alert(data.Result.Message);
}
}).fail(function () {
})
}
});
</script>
}
以上是非常完整的檔案管理系統
元哥的筆記