ASP.NET MVC4使用MongoDB做的相簿管理
阿新 • • 發佈:2018-12-24
TIPS:1.Image轉成Base64儲存到mongodb欄位
2.資料模型是巢狀的關聯
首先定義Model層:
public class Photo : IEquatable<Photo> { [Required] public string PhotoName { get; set; } [Required] public string PhotoDescription { get; set; } public string ServerPath { get; set; } public Photo() { } public Photo(string name, string desc) { PhotoName = name; PhotoDescription = desc; } public bool Equals(Photo other) { return string.Equals(PhotoName, other.PhotoName); } } public interface IAlbumIterable { bool HasNext(); Photo Current(); Photo Next(); } public interface IPhotosAggregable { IAlbumIterable GetIterator(); } public class AlbumIterator : IAlbumIterable { private Album collection; private int count; public AlbumIterator(Album album) { collection = album; } public Photo Current() { if (count < collection.Count) return collection[count++]; else throw new IndexOutOfRangeException(); } public bool HasNext() { if (count < collection.Count - 1) return true; else return false; } public Photo Next() { if (HasNext()) return collection[++count]; else throw new IndexOutOfRangeException(); } } public class Album : IPhotosAggregable { [BsonId] public ObjectId Id { get; set; } [Required] public string Name { get; set; } [Required] public string Description { get; set; } public string Owner { get; set; } public Photo TitlePhoto { get; set; } [BsonDateTimeOptions(Kind = DateTimeKind.Local,Representation =BsonType.DateTime)] public DateTime CreationTime { get; set; } public IList<Photo> Pictures { get; set; } public Album() { Pictures = new List<Photo>(); TitlePhoto = new Photo(); } public Album(string name, string owner, Photo pic) { Name = name; Owner = owner; TitlePhoto = pic; Pictures = new List<Photo>(); TitlePhoto = new Photo(); } public bool InsertPicture(Photo pic) { if (!Pictures.Contains(pic)) { Pictures.Add(pic); return true; } else throw new ArgumentException(); } public bool InsertPictures(List<Photo> photos) { foreach(var photo in photos) { if (!Pictures.Contains(photo)) { Pictures.Add(photo); } else throw new ArgumentException(); } return true; } public bool RemovePicture(Photo pic) { Pictures.Remove(pic); return true; } public int Count { get { return Pictures.Count; } } public Photo this[int index] { get { return Pictures[index]; } set { Pictures[index] = value; } } public IAlbumIterable GetIterator() { return new AlbumIterator(this); } }
Services層的MongoAlbumPerformer.cs和ServerPathFinder.cs程式碼如下:
public class MongoAlbumPerformer { protected static IMongoClient client; protected static IMongoDatabase database; private static IMongoCollection<Album> collection; private string collectionName; public MongoAlbumPerformer(string databaseName, string collectionName) { client = new MongoClient(ConfigurationManager.ConnectionStrings["mongoDB"].ConnectionString); database = client.GetDatabase(databaseName); this.collectionName = collectionName; collection = database.GetCollection<Album>(collectionName, new MongoCollectionSettings { AssignIdOnInsert = true }); } public void SetCollection(string collectionName) { this.collectionName = collectionName; collection = database.GetCollection<Album>(collectionName); } public void CreateAlbum(Album album) { var document = new Album { Name = album.Name, Owner = HttpContext.Current.User.Identity.Name, Description = album.Description, CreationTime = DateTime.Now, TitlePhoto = album.TitlePhoto, Pictures = album.Pictures }; collection.InsertOne(document); } public List<Album> GetAlbumsByUserName(string username) { var projection = Builders<Album>.Projection .Include(a => a.Name) .Include(a => a.Description) .Include(a => a.TitlePhoto) .Include(a=>a.CreationTime); var result = collection .Find(a => a.Owner == HttpContext.Current.User.Identity.Name) .Project<Album>(projection).ToList(); return result; } public Album GetPicturesByAlbumName(string albumName) { var projection = Builders<Album>.Projection .Include(a => a.Pictures); var result = collection .Find(a => a.Owner == HttpContext.Current.User.Identity.Name & a.Name == albumName) .Project<Album>(projection).FirstOrDefault(); return result; } public void UpdateAlbumAddPhoto(string albumName, Photo photo) { var builder = Builders<Album>.Filter; var filter = builder.Eq(f => f.Name, albumName) & builder.Eq(f => f.Owner, HttpContext.Current.User.Identity.Name); var result = collection.Find(filter).FirstOrDefault(); if (result == null) throw new ArgumentException("No album of supplied name: {0}", albumName); else { var picture = new Photo { PhotoName = photo.PhotoName, PhotoDescription = photo.PhotoDescription, ServerPath = photo.ServerPath, }; var update = Builders<Album>.Update.Push(a => a.Pictures, picture); collection.UpdateOne(filter, update, new UpdateOptions { IsUpsert=true }); } } public void DeletePhotoFromAlbum(string albumName, string photoName) { var builder = Builders<Album>.Filter; var filter = builder.Eq(f => f.Name, albumName) & builder.Eq(f => f.Owner, HttpContext.Current.User.Identity.Name); var result = collection.Find(filter).SingleOrDefault(); if (result == null) throw new ArgumentException("No album of supplied name: {0}", albumName); else { var update = Builders<Album>.Update .PullFilter(a => a.Pictures, Builders<Photo>.Filter.Eq(p => p.PhotoName, photoName)); long count = collection.UpdateOne(filter, update).MatchedCount; } } }
public class ServerPathFinder { public string GetBase64ImageString(HttpPostedFileBase file) { string mime = Regex.Match(file.ContentType, @"(?<=image/)\w+").Value; byte[] bytes = new byte[file.ContentLength]; file.InputStream.Read(bytes, 0, file.ContentLength); return string.Format("data:image/{0};base64,{1}",mime, Convert.ToBase64String(bytes)); } }
AlbumController.cs程式碼如下:
public class AlbumController : Controller
{
MongoAlbumPerformer mongod = new MongoAlbumPerformer("test","albums");
[HttpPost]
public ActionResult AlbumPreview(Photo model, HttpPostedFileBase file, string albumName, string delete, string phot)
{
if (delete == "false")
{
if (file != null)
{
if (!file.ContentType.StartsWith("image"))
{
ModelState.AddModelError("file", "選擇正確的格式照片!");
}
else
{
ServerPathFinder finder = new ServerPathFinder();
model.ServerPath = finder.GetBase64ImageString(file);
}
if (ModelState.IsValid)
{
mongod.UpdateAlbumAddPhoto(albumName, model);
ModelState.Clear();
}
}
}
else
{
mongod.DeletePhotoFromAlbum(albumName, phot);
foreach(var error in ModelState.Values)
{
error.Errors.Clear();
}
}
ViewBag.AlbumTitle = albumName;
ViewBag.PhotoList = mongod.GetPicturesByAlbumName(albumName).Pictures;
return View();
}
public ActionResult AlbumPreview(string Name)
{
var album = mongod.GetPicturesByAlbumName(Name);
ViewBag.AlbumTitle = Name;
ViewBag.PhotoList = album.Pictures;
return View();
}
[HttpPost]
public ActionResult Create(Album model, HttpPostedFileBase file)
{
if (!file.ContentType.StartsWith("image"))
{
ModelState.AddModelError("file", "選擇正確的格式照片!");
}
else
{
ServerPathFinder finder = new ServerPathFinder();
model.TitlePhoto.ServerPath = finder.GetBase64ImageString(file);
}
if (ModelState.IsValid)
{
model.Owner = HttpContext.User.Identity.Name;
mongod.CreateAlbum(model);
}
var albums = mongod.GetAlbumsByUserName(HttpContext.User.Identity.Name);
ViewBag.Albums = albums;
return View();
}
public ActionResult Create()
{
var albums = mongod.GetAlbumsByUserName(HttpContext.User.Identity.Name);
ViewBag.Albums = albums;
return View();
}
}
部分view檢視:
Create.cshtml
@{
ViewBag.Title = "Create";
}
<h2>我的相簿</h2>
@Html.Partial("_MyAlbums", (List<Album>)ViewBag.Albums)
@using (Html.BeginForm("Create", "Album", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>建立新相簿: </h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Description, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.TitlePhoto, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="file" id="file" style="width: 100%;" data-val="true" data-val-required="要求標題圖片."/>
@Html.ValidationMessage("file",new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
@section scripts{
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$('img').click(function (data) {
});
</script>
}
AlbumPreview.cshtml@{
ViewBag.Title = "AlbumPreview";
}
@using (Html.BeginForm("AlbumPreview", "Album", FormMethod.Post, new { enctype = "multipart/form-data"}))
{
@Html.AntiForgeryToken()
{Html.RenderPartial("_Preview", (List<Photo>)ViewBag.PhotoList);}
<div class="form-horizontal">
<br />
<h4>新增新的照片:</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.PhotoName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.PhotoName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.PhotoName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.PhotoDescription, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.PhotoDescription, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.PhotoDescription, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">選擇照片:</label>
<div class="col-md-10">
<input type="file" name="file" id="file" style="width: 100%;" data-val="true" data-val-required="請選擇影象" />
@Html.ValidationMessage("file", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
<input type="hidden" name="albumName" id="albumName" value="@ViewBag.AlbumTitle" />
<input type="hidden" name="delete" id="delete" value="false" />
<input type="hidden" name="phot" id="phot" value="sraka" />
}
@section scripts{
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$(document).ready(function () {
var elements = document.getElementsByClassName("btn btn-xs btn-warning cancel");
for (var i = 0, len = elements.length; i < len; i++) {
elements[i].addEventListener("click", function () {
$('#delete').val(true);
var name = $(this).attr("id");
$('#phot').val(name);
$('#' + name).click();
});
}
})
</script>
}
_Preview.cshtml@{
ViewBag.Title = "_Preview";
}
<h2>Album <span style="color:royalblue;font-style:italic">@ViewBag.AlbumTitle</span></h2>
<div class="row">
@foreach (var photo in Model)
{
<div class="col-md-3">
<input type="submit" id="@photo.PhotoName" value="刪除" class="btn btn-xs btn-warning cancel" style="text-align:center;float:right" />
<img src="@photo.ServerPath" class="img-responsive img-thumbnail col-md-3" style="width:100%;height:180px" />
<label style="text-align:center;width:100%">@Html.DisplayNameFor(phot=>phot.PhotoName): @photo.PhotoName</label>
<label style="text-align:center;width:100%;font-weight:100">@photo.PhotoDescription</label>
</div>
}
</div>
執行專案結果如圖:
首頁建立相簿:
《車》相簿下的圖片示例,可以增加圖片,刪除圖片
《QQ》相簿下的圖片示例
mongodb資料儲存結構圖:
結束!--QQ827937686