1前言
上傳文件的接口設計有兩種風格,一種是整個項目只設置一個接口用來上傳,然后其他需要用到文件的地方,都只存一個引用ID;另一種是每個需要文件的地方單獨管理各自的文件。這倆各有優劣吧,本項目中選擇的是后者的風格,文章圖片和照片模塊又要能CRUD又要批量導入,還是各自管理文件比較好。
2圖片接口
說會正題,先介紹一下圖片相關接口。
圖片列表
首先CRUD是肯定有的,圖片列表的分頁查看也是有的,不過因為篩選功能沒有做,所以就不定義一個ViewModel作為參數了。
控制器代碼 StarBlog.Web/Apis/Blog/PhotoController.cs
[HttpGet]
public?ApiResponsePaged<Photo>?GetList(int?page?=?1,?int?pageSize?=?10)?{var?paged?=?_photoService.GetPagedList(page,?pageSize);return?new?ApiResponsePaged<Photo>?{Pagination?=?paged.ToPaginationMetadata(),Data?=?paged.ToList()};
}
跟博客前臺公用一套圖片列表邏輯,所以這部分抽出來放在service,代碼如下
StarBlog.Web/Services/PhotoService.cs
public?IPagedList<Photo>?GetPagedList(int?page?=?1,?int?pageSize?=?10)?{return?_photoRepo.Select.OrderByDescending(a?=>?a.CreateTime).ToList().ToPagedList(page,?pageSize);
}
單個圖片
獲取單個圖片,跟獲取文章的差不多,傳入ID,找不到就返回404,找到就返回圖片對象
[HttpGet("{id}")]
public?ApiResponse<Photo>?Get(string?id)?{var?photo?=?_photoService.GetById(id);return?photo?==?null??ApiResponse.NotFound($"圖片?{id}?不存在"):?new?ApiResponse<Photo>?{Data?=?photo};
}
圖片縮略圖
在本系列第20篇中,本項目已經實現了圖片顯示的優化,詳見:基于.NetCore開發博客項目 StarBlog - (20) 圖片顯示優化
除了 ImageSharp 組件提供的圖片縮略圖功能外,我這里還寫了另一個生成縮略圖的方法,這個方法有倆特點
直接在內存中生成返回,不會寫入緩存文件
生成的是Progressive JPEG格式,目前 ImageSharp 是不支持的,可以優化前端的加載速度
控制器代碼
[HttpGet("{id}/Thumb")]
public?async?Task<IActionResult>?GetThumb(string?id,?[FromQuery]?int?width?=?300)?{var?data?=?await?_photoService.GetThumb(id,?width);return?new?FileContentResult(data,?"image/jpeg");
}
service代碼
///?<summary>
///?生成Progressive?JPEG縮略圖?(使用?MagickImage)
///?</summary>
///?<param?name="width">設置為0則不調整大小</param>
public?async?Task<byte[]>?GetThumb(string?id,?int?width?=?0)?{var?photo?=?await?_photoRepo.Where(a?=>?a.Id?==?id).FirstAsync();using?(var?image?=?new?MagickImage(GetPhotoFilePath(photo)))?{image.Format?=?MagickFormat.Pjpeg;if?(width?!=?0)?{image.Resize(width,?0);}return?image.ToByteArray();}
}
這個 MagickImage 是用 C++ 寫的,在不同平臺上引用不同 native 庫,需要在 csproj 里面寫上配置,這樣發布的時候才會帶上對應的依賴庫,而且似乎在 CentOS 系統上會有坑…
<!--??復制?Magick?庫??-->
<PropertyGroup><MagickCopyNativeWindows>true</MagickCopyNativeWindows><MagickCopyNativeLinux>true</MagickCopyNativeLinux><MagickCopyNativeMacOS>true</MagickCopyNativeMacOS>
</PropertyGroup>
其他接口
還有一些接口,跟之前介紹的大同小異,再重復一次也意義不大,讀者有需要的話可以自行查看源碼。
刪除圖片
設置和取消推薦
重建圖片庫數據(更新每個圖片的尺寸等數據,一般情況下不需要用到)
批量導入(本系列的第9篇已經介紹過)詳見:基于.NetCore開發博客項目 StarBlog - (9) 圖片批量導入
3圖片文件上傳
這個同時也是圖片的添加接口
先定義DTO
public?class?PhotoCreationDto?{///?<summary>///?作品標題///?</summary>[Required(ErrorMessage?=?"作品標題不能為空")]public?string?Title?{?get;?set;?}///?<summary>///?拍攝地點///?</summary>[Required(ErrorMessage?=?"拍攝地點不能為空")]public?string?Location?{?get;?set;?}
}
控制器代碼
[Authorize]
[HttpPost]
public?ApiResponse<Photo>?Add([FromForm]?PhotoCreationDto?dto,?IFormFile?file)?{var?photo?=?_photoService.Add(dto,?file);return?!ModelState.IsValid??ApiResponse.BadRequest(ModelState):?new?ApiResponse<Photo>(photo);
}
因為上傳的同時還要附帶一些數據,需要使用 FormData 傳參,所以這里使用 [FromForm]
特性標記這個 dto 參數
IFormFile
類型的參數可以拿到上傳上來的文件
下面是service代碼
public?Photo?Add(PhotoCreationDto?dto,?IFormFile?photoFile)?{var?photoId?=?GuidUtils.GuidTo16String();var?photo?=?new?Photo?{Id?=?photoId,Title?=?dto.Title,CreateTime?=?DateTime.Now,Location?=?dto.Location,FilePath?=?Path.Combine("photography",?$"{photoId}.jpg")};var?savePath?=?Path.Combine(_environment.WebRootPath,?"media",?photo.FilePath);//?如果超出最大允許的大小,則按比例縮小const?int?maxWidth?=?2000;const?int?maxHeight?=?2000;using?(var?image?=?Image.Load(photoFile.OpenReadStream()))?{if?(image.Width?>?maxWidth)image.Mutate(a?=>?a.Resize(maxWidth,?0));if?(image.Height?>?maxHeight)image.Mutate(a?=>?a.Resize(0,?maxHeight));image.Save(savePath);}//?保存文件using?(var?fs?=?new?FileStream(savePath,?FileMode.Create))?{photoFile.CopyTo(fs);}//?讀取圖片的尺寸等數據photo?=?BuildPhotoData(photo);return?_photoRepo.Insert(photo);
}
這里對圖片做了一些處理,拋開這些細節,其實對上傳的文件,最關鍵的只有幾行保存代碼
using?(var?fs?=?new?FileStream("savePath",?FileMode.Create))?{photoFile.CopyTo(fs);
}
這樣就完成了文件上傳接口。
4系列文章
基于.NetCore開發博客項目 StarBlog - (1) 為什么需要自己寫一個博客?
基于.NetCore開發博客項目 StarBlog - (2) 環境準備和創建項目
基于.NetCore開發博客項目 StarBlog - (3) 模型設計
基于.NetCore開發博客項目 StarBlog - (4) markdown博客批量導入
基于.NetCore開發博客項目 StarBlog - (5) 開始搭建Web項目
基于.NetCore開發博客項目 StarBlog - (6) 頁面開發之博客文章列表
基于.NetCore開發博客項目 StarBlog - (7) 頁面開發之文章詳情頁面
基于.NetCore開發博客項目 StarBlog - (8) 分類層級結構展示
基于.NetCore開發博客項目 StarBlog - (9) 圖片批量導入
基于.NetCore開發博客項目 StarBlog - (10) 圖片瀑布流
基于.NetCore開發博客項目 StarBlog - (11) 實現訪問統計
基于.NetCore開發博客項目 StarBlog - (12) Razor頁面動態編譯
基于.NetCore開發博客項目 StarBlog - (13) 加入友情鏈接功能
基于.NetCore開發博客項目 StarBlog - (14) 實現主題切換功能
基于.NetCore開發博客項目 StarBlog - (15) 生成隨機尺寸圖片
基于.NetCore開發博客項目 StarBlog - (16) 一些新功能 (監控/統計/配置/初始化)
基于.NetCore開發博客項目 StarBlog - (17) 自動下載文章里的外部圖片
基于.NetCore開發博客項目 StarBlog - (18) 實現本地Typora文章打包上傳
基于.NetCore開發博客項目 StarBlog - (19) Markdown渲染方案探索
基于.NetCore開發博客項目 StarBlog - (20) 圖片顯示優化
基于.NetCore開發博客項目 StarBlog - (21) 開始開發RESTFul接口
基于.NetCore開發博客項目 StarBlog - (22) 開發博客文章相關接口
基于.NetCore開發博客項目 StarBlog - (23) 文章列表接口分頁、過濾、搜索、排序
基于.NetCore開發博客項目 StarBlog - (24) 統一接口數據返回格式
基于.NetCore開發博客項目 StarBlog - (25) 圖片接口與文件上傳