基于SqlSugar的开发框架循序渐进介绍(26)-- 实现本地上传、FTP上传、阿里云OSS上传三者合一处理
在前面介绍的随笔《基于SqlSugar的开发框架循序渐进介绍(7)-- 在文件上传模块中采用选项模式【Options】处理常规上传和FTP文件上传》中介绍过在文件上传处理的过程中,整合了本地文件上传和基于FTP方式的上传文件的处理整合。本篇随笔继续介绍文件上传的处理,基于选项模式【Options】方式整合基于阿里云OSS对象存储的处理方式。
1、选项模式【Options】的处理
文件上传处理应该由程序进行配置,决定使用那种方式,那么这里面我们为了弹性化处理, 在文件上传模块中采用选项模式【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文件配置项内容如下:

2、阿里云的OSS存储设置处理
对于阿里云的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;
}
最终我们上传的文件列表如上图所示。

3、在Vue3+ElementPlus+Vite的前端项目上测试前端上传文件的处理
我们在一个前端的编辑器@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的路径。

在数据库的文件记录中,我们可以看到对应的路径信息,如下所示。

以上就是我们针对不同的上传方式处理的操作,对于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上传三者合一处理
基于SqlSugar的开发框架循序渐进介绍(26)-- 实现本地上传、FTP上传、阿里云OSS上传三者合一处理的更多相关文章
- 基于SqlSugar的开发框架循序渐进介绍(3)-- 实现代码生成工具Database2Sharp的整合开发
我喜欢在一个项目开发模式成熟的时候,使用代码生成工具Database2Sharp来配套相关的代码生成,对于我介绍的基于SqlSugar的开发框架,从整体架构确定下来后,我就着手为它们量身定做相关的代码 ...
- 基于SqlSugar的开发框架循序渐进介绍(4)-- 在数据访问基类中对GUID主键进行自动赋值处理
我们在设计数据库表的时候,往往为了方便,主键ID一般采用字符串类型或者GUID类型,这样对于数据库表记录的迁移非常方便,而且有时候可以在处理关联记录的时候,提前对应的ID值.但有时候进行数据记录插入的 ...
- 基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转
在前面随笔,我们介绍过这个基于SqlSugar的开发框架,我们区分Interface.Modal.Service三个目录来放置不同的内容,其中Modal是SqlSugar的映射实体,Interface ...
- 基于SqlSugar的开发框架循序渐进介绍(6)-- 在基类接口中注入用户身份信息接口
在基于SqlSugar的开发框架中,我们设计了一些系统服务层的基类,在基类中会有很多涉及到相关的数据处理操作的,如果需要跟踪具体是那个用户进行操作的,那么就需要获得当前用户的身份信息,包括在Web A ...
- 基于SqlSugar的开发框架循序渐进介绍(8)-- 在基类函数封装实现用户操作日志记录
在我们对数据进行重要修改调整的时候,往往需要跟踪记录好用户操作日志.一般来说,如对重要表记录的插入.修改.删除都需要记录下来,由于用户操作日志会带来一定的额外消耗,因此我们通过配置的方式来决定记录那些 ...
- 基于SqlSugar的开发框架循序渐进介绍(12)-- 拆分页面模块内容为组件,实现分而治之的处理
在早期的随笔就介绍过,把常规页面的内容拆分为几个不同的组件,如普通的页面,包括列表查询.详细资料查看.新增资料.编辑资料.导入资料等页面场景,这些内容相对比较独立,而有一定的代码量,本篇随笔介绍基于V ...
- 基于SqlSugar的开发框架循序渐进介绍(13)-- 基于ElementPlus的上传组件进行封装,便于项目使用
在我们实际项目开发过程中,往往需要根据实际情况,对组件进行封装,以更简便的在界面代码中使用,在实际的前端应用中,适当的组件封装,可以减少很多重复的界面代码,并且能够非常简便的使用,本篇随笔介绍基于El ...
- 基于SqlSugar的开发框架循序渐进介绍(14)-- 基于Vue3+TypeScript的全局对象的注入和使用
刚完成一些前端项目的开发,腾出精力来总结一些前端开发的技术点,以及继续完善基于SqlSugar的开发框架循序渐进介绍的系列文章,本篇随笔主要介绍一下基于Vue3+TypeScript的全局对象的注入和 ...
- 基于SqlSugar的开发框架循序渐进介绍(15)-- 整合代码生成工具进行前端界面的生成
在前面随笔<基于SqlSugar的开发框架循序渐进介绍(12)-- 拆分页面模块内容为组件,实现分而治之的处理>中我们已经介绍过,对于相关的业务表的界面代码,我们已经尽可能把不同的业务逻辑 ...
- 基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理
在一个应用系统的开发框架中,往往很多地方需要用到缓存的处理,有些地方是为了便于记录用户的数据,有些地方是为了提高系统的响应速度,如有时候我们在发送一个短信验证码的时候,可以在缓存中设置几分钟的过期时间 ...
随机推荐
- vue、react配置gzip打包后,删除源文件deleteOriginalAssets: true,nginx需要的配置
1.删除源文件后,配置了gzip,当配置gzip删除源文件后,解决前端history问题,就会出现所有的都返回html,请求js.css也会返回html,页面会报错,如下配置即可 location / ...
- 使用python的turtle库画一个冰墩墩
目录 先看效果图 设置一个画布 画左手和手内 画轮廓和其他部分 画细节(眼睛.鼻子.嘴巴等) 画头部彩虹 画五环标志 最后(别忘记还有一个结束) 先看效果图 设置一个画布 点击查看代码 import ...
- 跨域获取iframe页面的url
一:跨域获取iframe页面的url 1.在使用iframe页面的js添加以下内容 <script> var host = window.location.href; var histor ...
- ASP.NET Core 读取配置文件信息
一:读取配置文件 先来看一下appsettings.json文件的内容,如下图: { "ConnectionStrings": { "ServerConnection&q ...
- HTML5第五章作业
5.1.3 html 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" ...
- MPC
Just for anyone searching for code. I found it here: https://drive.google.com/drive/folders/0BzLEHBD ...
- activiti引擎的表结构(仅记录用)
act_hi_*:'hi'表示 history,此前缀的表包含历史数据,如历史(结束)流程实例,变量,任务等等.act_ge_*:'ge'表示 general,此前缀的表为全局通用数据,用于不同场景中 ...
- 读取nrf52832的ADC,并且获取N个数组中的中间值
//****读取中间值****// short GetMedianNum(short * bArray, short iFilterLen) { short i,j,bTemp;// 排序循环 for ...
- 持续集成环境(6)-Tomcat安装和配置(编写中)
安装Tomcat8.5 把Tomcat压缩包上传到tomcat服务器(tomcat专用服务测试服务器.生产服务器) yum install java-1.8.0-openjdk* -y wget ht ...
- FreeType 矢量字体 测试移植(1)
之前有做过 ascii 和汉字库的字体点阵在lcd上显示的例子,都是按照指定大小的字库的点阵来显示的,所以一但选定了字体文件后,就固定了大小,不可变化,当然也可以存放各种 大小的字体文件,但这样的话就 ...