From e04ac0f5412708e3fee054ba41b56b3ba0fbefd3 Mon Sep 17 00:00:00 2001 From: Tsanie Lily Date: Fri, 26 May 2023 13:39:58 +0800 Subject: [PATCH] optimized --- Server/Controller/BaseController.cs | 22 +++ Server/Controller/BaseController.sqlite.cs | 10 ++ Server/Controller/EventApiController.cs | 156 ++++++++++++++++++--- Server/Controller/FlowerApiController.cs | 33 +++-- 4 files changed, 185 insertions(+), 36 deletions(-) diff --git a/Server/Controller/BaseController.cs b/Server/Controller/BaseController.cs index 7c1e268..2ac89b6 100644 --- a/Server/Controller/BaseController.cs +++ b/Server/Controller/BaseController.cs @@ -250,6 +250,28 @@ public abstract partial class BaseController : ControllerBase var path = Path.Combine(directory, file.Path); await System.IO.File.WriteAllBytesAsync(path, file.Content, token); } + + /// + /// 删除花草下的文件 + /// + /// 用户唯一 id + /// 花草唯一 id + /// 文件路径 + /// 返回是否已删除 + protected bool DeleteFile(int uid, int fid, string path) + { + var directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "uploads", uid.ToString(), fid.ToString()); + if (Directory.Exists(directory)) + { + path = Path.Combine(directory, path); + if (System.IO.File.Exists(path)) + { + System.IO.File.Delete(path); + return true; + } + } + return false; + } } /// diff --git a/Server/Controller/BaseController.sqlite.cs b/Server/Controller/BaseController.sqlite.cs index abdb3b5..a200d18 100644 --- a/Server/Controller/BaseController.sqlite.cs +++ b/Server/Controller/BaseController.sqlite.cs @@ -71,6 +71,16 @@ partial class BaseController return database.Database.ExecuteSql($"UPDATE \"users\" SET \"avatar\" = NULL WHERE \"uid\" = {uid}"); } + /// + /// 添加事件项 + /// + /// 事件对象 + /// + protected int AddRecordItem(RecordItem item) + { + return database.Database.ExecuteSql($"INSERT INTO \"records\"(\"uid\",\"fid\",\"eid\",\"date\",\"byuid\",\"byname\",\"memo\") VALUES({item.OwnerId},{item.FlowerId},{item.EventId},{item.DateUnixTime},{item.ByUserId},{item.ByUserName},{item.Memo})"); + } + /// /// 添加照片项 /// diff --git a/Server/Controller/EventApiController.cs b/Server/Controller/EventApiController.cs index 64a14bd..e0df289 100644 --- a/Server/Controller/EventApiController.cs +++ b/Server/Controller/EventApiController.cs @@ -3,6 +3,7 @@ using Blahblah.FlowerStory.Server.Data.Model; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations; +using System.IO; namespace Blahblah.FlowerStory.Server.Controller; @@ -293,7 +294,6 @@ public class EventApiController : BaseController var record = database.Records.SingleOrDefault(r => r.Id == update.Id && r.OwnerId == user.Id); if (record == null) { - SaveDatabase(); return NotFound(update.Id); } record.FlowerId = update.FlowerId; @@ -360,10 +360,11 @@ public class EventApiController : BaseController return NotFound(); } + SaveDatabase(); + var record = database.Records.SingleOrDefault(r => r.Id == id && r.OwnerId == user.Id); if (record == null) { - SaveDatabase(); return NotFound(id); } if (photo.Length > 0) @@ -371,33 +372,33 @@ public class EventApiController : BaseController var file = WrapFormFile(photo); if (file == null) { - SaveDatabase(); return BadRequest(); } - var p = new PhotoItem - { - FlowerId = record.FlowerId, - RecordId = id, - FileType = file.FileType, - FileName = file.Filename, - Path = file.Path, - DateUploadUnixTime = user.ActiveDateUnixTime ?? DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - }; - database.Photos.Add(p); - try { - await WriteToFile(user.Id, record.FlowerId, file); + await ExecuteTransaction(async token => + { + var p = new PhotoItem + { + FlowerId = record.FlowerId, + RecordId = id, + FileType = file.FileType, + FileName = file.Filename, + Path = file.Path, + DateUploadUnixTime = user.ActiveDateUnixTime ?? DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + }; + AddPhotoItem(p); + + await WriteToFile(user.Id, record.FlowerId, file, token); + }); } catch (Exception ex) { - SaveDatabase(); return Problem(ex.ToString(), "api/event/add_photo"); // TODO: Logger } } - SaveDatabase(); return NoContent(); } @@ -451,14 +452,12 @@ public class EventApiController : BaseController if (photos == null || photos.Length == 0) { - SaveDatabase(); return BadRequest(); } var record = database.Records.SingleOrDefault(r => r.Id == id && r.OwnerId == user.Id); if (record == null) { - SaveDatabase(); return NotFound(id); } @@ -503,6 +502,125 @@ public class EventApiController : BaseController return NoContent(); } + /// + /// 移除事件关联照片 + /// + /// + /// 请求示例: + /// + /// DELETE /api/event/remove_photo + /// Authorization: authorization id + /// + /// 参数: + /// + /// id: int + /// + /// + /// 图片唯一 id + /// 移除成功则返回 HTTP 204 + /// 移除成功 + /// 未找到登录会话或已过期或图片所有者不符 + /// 用户已禁用 + /// 未找到关联用户或者照片 + [Route("remove_photo", Name = "removeEventPhoto")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [HttpDelete] + public ActionResult RemoveEventPhoto([FromQuery][Required] int id) + { + var (result, user) = CheckPermission(); + if (result != null) + { + return result; + } + if (user == null) + { + return NotFound(); + } + + var photo = database.Photos.Where(p => p.Id == id).Include(p => p.Record).SingleOrDefault(); + if (photo == null) + { + return NotFound(); + } + if (photo.Record != null && photo.Record.OwnerId != user.Id) + { + return Unauthorized(); + } + + database.Photos.Remove(photo); + + SaveDatabase(); + + if (photo.Record != null) + { + DeleteFile(user.Id, photo.Record.FlowerId, photo.Path); + } + + return NoContent(); + } + + /// + /// 批量移除事件关联的照片 + /// + /// + /// 请求示例: + /// + /// POST /api/event/remove_photos + /// Authorization: authorization id + /// [ + /// 2, 4, 5, 11 + /// ] + /// + /// + /// 要移除的事件关联图片唯一 id 的数组 + /// 会话有效则返回操作影响的数据库行数 + /// 返回操作影响的数据库行数 + /// 未找到登录会话或已过期 + /// 用户已禁用 + /// 未找到关联用户 + [Route("remove_photos", Name = "removeEventPhotos")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [HttpPost] + [Consumes("application/json")] + public ActionResult RemoveEventPhotos([FromBody] int[] ids) + { + var (result, user) = CheckPermission(); + if (result != null) + { + return result; + } + if (user == null) + { + return NotFound(); + } + + if (database.Photos.Any(p => ids.Contains(p.Id) && database.Records.Any(r => r.Id == p.RecordId && r.OwnerId != user.Id))) + { + return Unauthorized(); + } + + var photos = database.Photos.Where(p => ids.Contains(p.Id)).Include(p => p.Record).ToList(); + var count = database.Photos.Where(p => ids.Contains(p.Id)).ExecuteDelete(); + + SaveDatabase(); + + foreach (var photo in photos) + { + if (photo.Record != null) + { + DeleteFile(user.Id, photo.Record.FlowerId, photo.Path); + } + } + + return Ok(count); + } + /// /// 获取事件关联的照片列表 /// diff --git a/Server/Controller/FlowerApiController.cs b/Server/Controller/FlowerApiController.cs index 4f93517..e6b85e8 100644 --- a/Server/Controller/FlowerApiController.cs +++ b/Server/Controller/FlowerApiController.cs @@ -316,7 +316,6 @@ public class FlowerApiController : BaseController var flower = database.Flowers.SingleOrDefault(f => f.Id == update.Id && f.OwnerId == user.Id); if (flower == null) { - SaveDatabase(); return NotFound(update.Id); } flower.CategoryId = update.CategoryId; @@ -378,7 +377,6 @@ public class FlowerApiController : BaseController var flower = database.Flowers.SingleOrDefault(f => f.Id == id && f.OwnerId == user.Id); if (flower == null) { - SaveDatabase(); return NotFound(id); } if (photo.Length > 0) @@ -386,7 +384,6 @@ public class FlowerApiController : BaseController var file = WrapFormFile(photo); if (file == null) { - SaveDatabase(); return BadRequest(); } @@ -406,30 +403,32 @@ public class FlowerApiController : BaseController }; database.Records.Add(record); } - - var cover = new PhotoItem - { - FlowerId = id, - Record = record, - FileType = file.FileType, - FileName = file.Filename, - Path = file.Path, - DateUploadUnixTime = now - }; - database.Photos.Add(cover); + SaveDatabase(); try { - await WriteToFile(user.Id, id, file); + await ExecuteTransaction(async token => + { + var cover = new PhotoItem + { + FlowerId = id, + RecordId = record.Id, + FileType = file.FileType, + FileName = file.Filename, + Path = file.Path, + DateUploadUnixTime = now + }; + AddPhotoItem(cover); + + await WriteToFile(user.Id, id, file, token); + }); } catch (Exception ex) { - SaveDatabase(); return Problem(ex.ToString(), "api/flower/add_cover"); // TODO: Logger } } - SaveDatabase(); return NoContent(); }