在前面介紹的隨筆《基於SqlSugar的開發框架循序漸進介紹(7)-- 在檔案上傳模組中採用選項模式【Options】處理常規上傳和FTP檔案上傳》中介紹過在檔案上傳處理的過程中,整合了本地檔案上傳和基於FTP方式的上傳檔案的處理整合。本篇隨筆繼續介紹檔案上傳的處理,基於選項模式【Options】方式整合基於阿里雲OSS物件儲存的處理方式。
檔案上傳處理應該由程式進行設定,決定使用那種方式,那麼這裡面我們為了彈性化處理, 在檔案上傳模組中採用選項模式【Options】處理常規上傳和FTP檔案上傳的設定引數資訊。
微軟引入選項模式,它是用於設定框架服務使用的設定. 選項模式由Microsoft.Extensions.OptionsNuGet包實現,除了ASP.NET Core應用,它還適用於任何型別的應用程式,如果需要了解,微軟的檔案詳細解釋了選項模式。
選項模式的限制之一是你只能解析(注入) IOptions <MyOptions>
並在依賴注入設定完成(即所有模組的ConfigureServices
方法完成)後獲取選項值。如果你正在開發一個模組,可能需要讓開發者能夠設定一些選項,並在依賴注入註冊階段使用這些選項. 你可能需要根據選項值設定其他服務或更改依賴注入的註冊程式碼。IOptions<>是單例,因此一旦生成了,除非通過程式碼的方式更改,它的值是不會更新的。
之前介紹過的檔案上傳處理,
一個是本地檔案處理,一個是FTP檔案處理,它們選擇那種方式,依賴於設定引數的資訊,如下示意圖所示。
當我們增加了物件儲存OSS方式後,可以擴充套件下這個圖示如下所示。
在本地檔案處理過程中,如果是Web API方式呼叫服務層,那麼就在Web API所在的檔案系統中,如果是Winform介面直接呼叫服務層,那麼就是在當前系統中處理檔案,這種方式可以有效的管理我們的檔案資訊。
在FTP檔案處理過程中,則是根據選項引數的資訊,呼叫FluentFTP類庫進行檔案的上傳操作。
在OSS物件儲存處理過程中,我們一般基於阿里雲、騰訊雲等這些雲服務OSS的處理方式,一般它們會提供相應開發語言的SDK,我們參照並進行整合即可。
基於選項模式,根據我們的處理方式,我們定義一個物件,用於承載上傳引數的資訊,如下程式碼所示。
/// <summary> /// 檔案上傳處理的選項資訊 /// </summary> public class UploadSettingOptions { /// <summary> /// 可指定的儲存實體地址,如C:\\Attachment,如果沒有設定項AttachmentBasePath,則預設一個相對目錄。 /// </summary> public string AttachmentBasePath { get; set; } /// <summary> /// 指定附件上傳的方式,如ftp為FTP方式,為空則為普通方式 /// </summary> public string AttachmentUploadType { get; set; } /// <summary> /// FTP上傳設定 /// </summary> public FtpProviderOptions FtpProvider { get; set; } /// <summary> /// OSS儲存的設定 /// </summary> public OSSProviderOptions OSSProvider { get; set; } }
其中本地介紹OSS儲存處理的設定選項物件如下所示。
/// <summary> /// OSS物件儲存設定選項 /// </summary> public sealed class OSSProviderOptions { /// <summary> /// 指定提供商 /// </summary> public OSSProvider Provider { get; set; } /// <summary> /// 終結點 /// </summary> public string Endpoint { get; set; } public string AccessKey { get; set; } public string SecretKey { get; set; } public string Region { get; set; } public bool IsEnableHttps { get; set; } = true; public bool IsEnableCache { get; set; } public string Bucket { get; set; } }
對應WebAPI的appSettngs.json檔案設定項內容如下:
對於阿里雲的OSS來說,對應的AccesKey和SecretKey自己可以通過檢視賬戶的資訊可以獲取到。
我們開始需要新增一個Bucket節點,用來存放相關的檔案,並且需要開啟對應的許可權,如下所示。
一旦正式允許可以上傳檔案,那麼檔案儲存在對應的Bucket專案中,如下所示。
準備好這些前期工作後,我們如果需要在WebAPI端進行OSS儲存的處理,可以利用阿里雲的OSS 的SDK進行處理即可,如下所示。
SDK的常規使用很簡單,我們可以參考它的aliyun-oss-csharp-sdk 案例來上傳處理即可。
例如它的上傳檔案的處理程式碼如下所示:
OssClient client = new OssClient(endpoint, accessKeyId, accessKeySecret); client.PutObject(bucketName, key, filePathToUpload);
在檔案處理的通用上傳處理常式裡面,我們根據設定內容選擇不同的上傳模式。
/// <summary> /// 上傳檔案(根據組態檔選擇合適的上傳方式) /// </summary> /// <param name="info">檔案資訊(包含流資料)</param> /// <returns></returns> public async Task<CommonResult> Upload(FileUploadInfo info) { var uploadType = this._options.AttachmentUploadType; if (string.IsNullOrEmpty(uploadType)) { return await this.UploadByNormal(info); } else if (uploadType.Equals("ftp", StringComparison.OrdinalIgnoreCase)) { return await this.UploadByFTP(info); } else if(uploadType.Equals("oss", StringComparison.OrdinalIgnoreCase)) { return await this.UploadByOSS(info); } else { throw new ArgumentException("AttachmentUploadType設定指定了無效的值, 請置空, 填寫ftp或者填寫oss。"); } }
由於本篇主要介紹OSS的物件儲存方式,因此我們來看看對應的OSS上傳處理的操作。
和其他上傳(如FTP上傳)方式類似,我們也是構建對應的資訊後呼叫OSS的SDK處理即可,如下程式碼所示。
/// <summary> /// 使用阿里雲的OSS服務上傳檔案 /// </summary> /// <param name="info"></param> /// <returns></returns> public async Task<CommonResult> UploadByOSS(FileUploadInfo info) { var result = new CommonResult(); var ossOptions = this._options.OSSProvider; if(ossOptions != null) { //上傳獲得的相對路徑 string category = info.Category; if (string.IsNullOrEmpty(category)) { category = "Photo"; } //OSS的檔案路徑不能以正斜線(/)或者反斜線(\)字元開頭。 //確定日期時間目錄(格式:yyyy-MM),不存在則建立 string savePath = string.Format("{0}-{1:D2}/{2}", DateTime.Now.Year, DateTime.Now.Month, category); var ext = FileUtil.GetExtension(info.FileName); var finalName = string.Format("{0}{1}", Guid.NewGuid().ToString(), ext);//FileUtil.GetFileName(file); var filePath = string.Concat(savePath, "/", finalName); var stream = FileUtil.BytesToStream(info.FileData); //使用阿里雲的OSS服務上傳檔案 var client = new OssClient(ossOptions.Endpoint, ossOptions.AccessKey, ossOptions.SecretKey); client.PutObject(ossOptions.Bucket, filePath, stream); //基礎路徑和部分路徑 info.BasePath = $"{(ossOptions.IsEnableHttps ? "https" : "http")}://{ossOptions.Bucket}.{ossOptions.Endpoint}"; info.SavePath = filePath; info.AddTime = DateTime.Now; result.Success = await base.InsertAsync(info); if (result.Success) { //記錄返回值, Data1為具體的URL路徑 //生成外連地址 方便前端預覽 result.Data1 = info.BasePath.UriCombine(savePath); result.Data2 = savePath; } else { result.ErrorMessage = "資料寫入資料庫出錯。"; } } else { result.ErrorMessage = "OSS設定資訊不正確或沒有啟用"; } return result; }
最終我們上傳的檔案列表如上圖所示。
我們在一個前端的編輯器 @wangeditor 上整合圖片上傳的處理來展示這個OSS物件儲存的操作。案例需要前端專案安裝對應的外掛,如下所示。
前端頁面參照外掛物件的程式碼如下所示
<div class="wangeditor"> <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" /> <Editor style="height: 500px; overflow-y: hidden" v-model="valueHtml" :defaultConfig="editorConfig" :mode="mode" @onCreated="handleCreated" /> </div>
在指令碼程式碼中引入物件的樣式和物件。
<script setup lang="ts"> import '@wangeditor/editor/dist/css/style.css'; // 引入 css import { Editor, Toolbar } from '@wangeditor/editor-for-vue'; defineOptions({ name: 'Editor' }); const mode = 'default'; // 編輯器範例,必須用 shallowRef const editorRef = shallowRef();
為了設定上傳圖片檔案的處理操作,我們需要根據編輯器的介紹,以及我們WebAPI端的處理常式定義,在指令碼部分中增加對應的設定資訊,如下程式碼所示
const editorConfig = { placeholder: '請輸入內容...', MENU_CONF: { // 設定預設字號 // 設定上傳圖片 uploadImage: { // 上傳圖片請求介面路徑 server: '/api/FileUpload/PostUpload', // 後端接收的檔名稱 fieldName: 'multipartFile', maxFileSize: 10 * 1024 * 1024, // 上傳圖片10M // 上傳的圖片型別 allowedFileTypes: ['image/*'], // 自定義增加 http header headers: { Authorization: 'Bearer ' + getAccessToken() }, // 自定義上傳引數,例如傳遞驗證的 token 等。引數會被新增到 formData 中,一起上傳到伺服器端。 meta: { guid: '', folder: '檔案圖片' }, // 將 meta 拼接到 url 引數中,預設 false metaWithUrl: false, // 小於該值就插入 base64 格式(而不上傳),預設為 0 base64LimitSize: 10 * 1024, // 10MB // 自定義上傳圖片返回格式【後端返回的格式】 customInsert(res: any, insertFn: InsertFnType) { console.log(res); if (!res.success) { ElMessage.error('上傳檔案失敗,' + res.error); return; } // 從 res 中找到 url alt href ,然後插入圖片 ,根據後端實際返回的欄位來 var result = res.result as Array<ResponseFileInfo>; if (result.length > 0) { console.log(result[0]); insertFn(result[0].url, result[0].name, result[0].url); } }, // 單個檔案上傳成功之後 onSuccess(file: File, res: any) { if (res.success) { ElMessage.success(`${file.name} 上傳成功`); return; } else { ElMessage.warning(`${file.name} 上傳出了點異常`); return; } }, // 單個檔案上傳失敗 onFailed(file: File, res: any) { console.log(res); ElMessage.error(`${file.name} 上傳失敗`); }, // 上傳錯誤,或者觸發 timeout 超時 onError(file: File, err: any, res: any) { console.log(err, res); ElMessage.error(`${file.name} 上傳出錯`); } } } };
其中主要的就是需要增加授權的令牌頭部資訊,以及對應上傳需要用到的引數,還有就是返回的介面物件裡面,需要根據Web API的定義,然後轉換為本地識別的類別進行展示即可,如定義的 customInsert 函數。
檔案上傳成功後,可以看到在編輯器中插入了對應的圖片檔案,圖片地址指向的是阿里雲OSS的路徑。
在資料庫的檔案記錄中,我們可以看到對應的路徑資訊,如下所示。
如果我們需要在專案中實現業務的圖片上傳功能,如下介面所示的效果。
可以參考隨筆《基於SqlSugar的開發框架循序漸進介紹(13)-- 基於ElementPlus的上傳元件進行封裝,便於專案使用》介紹內容進行自定義上傳檔案的處理即可。
<el-form-item label="資料檔案"> <my-upload v-model="viewForm.attachGUID" :data="{ guid: viewForm.attachGUID, folder: '使用者圖片' }" disabled /> </el-form-item>
以上就是我們針對不同的上傳方式處理的操作,對於OSS的檔案上傳,我們通過整合阿里雲的OSS的SDK,直接呼叫進行處理即可,非常方便,對於其他類似的平臺,也可以針對它們提供的SDK進行擴充套件即可。
SqlSugar開發框架介紹:https://www.iqidi.com/Framework/sugarIndex.htm
系列文章:
《基於SqlSugar的開發框架的循序漸進介紹(1)--框架基礎類的設計和使用》
《基於SqlSugar的開發框架循序漸進介紹(2)-- 基於中間表的查詢處理》
《基於SqlSugar的開發框架循序漸進介紹(3)-- 實現程式碼生成工具Database2Sharp的整合開發》
《基於SqlSugar的開發框架循序漸進介紹(4)-- 在資料存取基礎類別中對GUID主鍵進行自動賦值處理 》
《基於SqlSugar的開發框架循序漸進介紹(5)-- 在服務層使用介面注入方式實現IOC控制反轉》
《基於SqlSugar的開發框架循序漸進介紹(6)-- 在基礎類別介面中注入使用者身份資訊介面 》
《基於SqlSugar的開發框架循序漸進介紹(7)-- 在檔案上傳模組中採用選項模式【Options】處理常規上傳和FTP檔案上傳》
《基於SqlSugar的開發框架循序漸進介紹(8)-- 在基礎類別函數封裝實現使用者操作紀錄檔記錄》
《基於SqlSugar的開發框架循序漸進介紹(9)-- 結合Winform控制元件實現欄位的許可權控制》
《基於SqlSugar的開發框架循序漸進介紹(10)-- 利用axios元件的封裝,實現對後端API資料的存取和基礎類別的統一封裝處理》
《基於SqlSugar的開發框架循序漸進介紹(11)-- 使用TypeScript和Vue3的Setup語法糖編寫頁面和元件的總結》
《基於SqlSugar的開發框架循序漸進介紹(12)-- 拆分頁面模組內容為元件,實現分而治之的處理》
《基於SqlSugar的開發框架循序漸進介紹(13)-- 基於ElementPlus的上傳元件進行封裝,便於專案使用》
《基於SqlSugar的開發框架循序漸進介紹(14)-- 基於Vue3+TypeScript的全域性物件的注入和使用》
《基於SqlSugar的開發框架循序漸進介紹(15)-- 整合程式碼生成工具進行前端介面的生成》
《基於SqlSugar的開發框架循序漸進介紹(16)-- 工作流模組的功能介紹》
《基於SqlSugar的開發框架循序漸進介紹(17)-- 基於CSRedis實現快取的處理》
《基於SqlSugar的開發框架循序漸進介紹(18)-- 基於程式碼生成工具Database2Sharp,快速生成Vue3+TypeScript的前端介面和Winform端介面》
《基於SqlSugar的開發框架循序漸進介紹(19)-- 基於UniApp+Vue的移動前端的功能介紹》
《基於SqlSugar的開發框架循序漸進介紹(20)-- 在基於UniApp+Vue的行動端實現多條件查詢的處理》
《基於SqlSugar的開發框架循序漸進介紹(21)-- 在工作流列表頁面中增加一些跳脫資訊的輸出,在後端進行內容轉換》
《基於SqlSugar的開發框架循序漸進介紹(22)-- Vue3+TypeScript的前端工作流模組中實現統一的表單編輯和表單詳情檢視處理 》
《基於SqlSugar的開發框架循序漸進介紹(23)-- Winform端管理系統中平滑增加對Web API對接的需求》
《基於SqlSugar的開發框架循序漸進介紹(24)-- 使用Serialize.Linq對Lambda表示式進行序列化和反序列化 》
基於SqlSugar的開發框架循序漸進介紹(25)-- 基於SignalR實現多端的訊息通訊
基於SqlSugar的開發框架循序漸進介紹(26)-- 實現本地上傳、FTP上傳、阿里雲OSS上傳三者合一處理