基于SqlSugar的开发框架循序渐进介绍(7)-- 在文件上传模块中采用选项模式 ...

立山  金牌会员 | 2022-6-20 10:45:31 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 901|帖子 901|积分 2703

在基于SqlSugar的开发框架的服务层中处理文件上传的时候,我们一般有两种处理方式,一种是常规的把文件存储在本地文件系统中,一种是通过FTP方式存储到指定的FTP服务器上。这种处理应该由程序进行配置,决定使用那种方式,那么这里面我们为了弹性化处理, 在文件上传模块中采用选项模式【Options】处理常规上传和FTP文件上传的配置参数信息。
微软引入选项模式,它是用于配置框架服务使用的设置. 选项模式由Microsoft.Extensions.OptionsNuGet包实现,除了ASP.NET Core应用,它还适用于任何类型的应用程序,如果需要了解,微软的文档详细解释了选项模式。
选项模式的限制之一是你只能解析(注入) IOptions  并在依赖注入配置完成(即所有模块的ConfigureServices方法完成)后获取选项值。如果你正在开发一个模块,可能需要让开发者能够设置一些选项,并在依赖注入注册阶段使用这些选项. 你可能需要根据选项值配置其他服务或更改依赖注入的注册代码。IOptions是单例,因此一旦生成了,除非通过代码的方式更改,它的值是不会更新的。
1、文件上传处理

在前面我们介绍过,文件上传处理的逻辑中有两部分,一个是本地文件处理,一个是FTP文件处理,它们选择那种方式,依赖于配置参数的信息,如下示意图所示。

在本地文件处理过程中,如果是Web API方式调用服务层,那么就在Web API所在的文件系统中,如果是Winform界面直接调用服务层,那么就是在当前系统中处理文件,这种方式可以有效的管理我们的文件信息。
在FTP文件处理过程中,则是根据选项参数的信息,调用FluentFTP类库进行文件的上传操作。
在Winform界面中上传文件的界面如下所示,它对于采用哪种方式是不知道的,具体由配置参数决定。

而所有的附件信息我们存储在数据库里面,文件则存放在对应的文件夹里面,可以统一进行管理查看和管理。

 
2、选项模式【Options】的处理 

 首先根据我们的处理方式,我们定义一个对象,用于承载上传参数的信息,如下代码所示。
  1.     /// <summary>
  2.     /// 文件上传处理的选项信息
  3.     /// </summary>
  4.     public class UploadSettingOptions
  5.     {
  6.         /// <summary>
  7.         /// 可指定的存储物理地址,如C:\\Attachment,如果没有配置项AttachmentBasePath,则默认一个相对目录。
  8.         /// </summary>
  9.         public string AttachmentBasePath { get; set; }
  10.         /// <summary>
  11.         /// 指定附件上传的方式,如ftp为FTP方式,为空则为普通方式
  12.         /// </summary>
  13.         public string AttachmentUploadType { get; set; }
  14.         /// <summary>
  15.         /// FTP服务地址
  16.         /// </summary>
  17.         public string FtpServer { get; set; }
  18.         /// <summary>
  19.         /// FTP用户名
  20.         /// </summary>
  21.         public string FtpUser { get; set; }
  22.         /// <summary>
  23.         /// FTP密码
  24.         /// </summary>
  25.         public string FtpPassword { get; set; }
  26.         /// <summary>
  27.         /// FTP的基础路径,如可以指定为IIS的路径:http://www.iqidi.com:8000 ,方便下载打开
  28.         /// </summary>
  29.         public string FtpBaseUrl { get; set; }
  30.     }
复制代码
然后在项目中添加Microsoft.Extensions.Options引用。
我们定义文件上传服务类的和它的构造函数,以便于选项模式的处理。
  1.     /// <summary>
  2.     /// 上传附件信息 应用层服务接口实现
  3.     /// </summary>
  4.     public class FileUploadService : MyCrudService<FileUploadInfo,string, FileUploadPagedDto>, IFileUploadService
  5.     {
  6.         //微软引入选项模式,它是用于配置框架服务使用的设置. 选项模式由Microsoft.Extensions.Options NuGet包实现
  7.         //在你需要获得一个选项值时,将 IOptions<TOption> 服务注入到你的类中,使用它的 .Value 属性得到值.
  8.         private readonly UploadSettingOptions _options;
  9.         /// <summary>
  10.         /// 参数化构造,注入上传处理设置信息
  11.         /// </summary>
  12.         /// <param name="options"></param>
  13.         public FileUploadService(<strong>IOptions<UploadSettingOptions></strong> options)
  14.         {
  15.             _options = options.Value;
  16.         }
复制代码
我们看到这里提供了一个注入接口的参数信息,这样完成参数的注入加载后,我们在该服务类调用的时候,就可以使用它的选项参数信息了。
例如我们在其中通用的上传处理方法上如下所示。
  1.         /// <summary>
  2.         /// 上传文件(根据配置文件选择合适的上传方式)
  3.         /// </summary>
  4.         /// <param name="info">文件信息(包含流数据)</param>
  5.         /// <returns></returns>
  6.         public async Task<CommonResult> Upload(FileUploadInfo info)
  7.         {
  8.             var uploadType = this.<strong>_options</strong>.<strong>AttachmentUploadType</strong>;
  9.             if (string.IsNullOrEmpty(uploadType))
  10.             {
  11.                 return await this.UploadByNormal(info);
  12.             }
  13.             else if (uploadType.Equals("ftp", StringComparison.OrdinalIgnoreCase))
  14.             {
  15.                 return await this.UploadByFTP(info);
  16.             }
  17.             else
  18.             {
  19.                 throw new ArgumentException("AttachmentUploadType配置指定了无效的值, 请置空或者填写ftp。");
  20.             }
  21.         }
复制代码
我们来通过读取选项参数的信息,来决定采用哪种上传文件的方式。
我们在基于.net framewrok的Winform项目App.config中指定下面的配置信息
  1.   <appSettings>
  2.    
  3.    
  4.     <add key="AttachmentBasePath" value="" />
  5.    
  6.     <add key="AttachmentUploadType" value="" />
  7.    
  8.     <add key="FtpServer" value="114.215.106.96" />
  9.     <add key="FtpUser" value="web2" />
  10.     <add key="FtpPassword" value="" />
  11.    
  12.     <add key="FtpBaseUrl" value="http://www.iqidi.com/ftp" />
  13.   </appSettings>
复制代码
而在项目启动的时候,我们需要注入选项参数的内容,以达到完成配置文件信息的读取。
  1.         /// <summary>
  2.         /// 应用程序的主入口点。
  3.         /// </summary>
  4.         [STAThread]
  5.         static void Main()
  6.         {
  7.             // IServiceCollection负责注册
  8.             IServiceCollection services = new ServiceCollection();//添加IApiUserSession实现类
  9.             services.AddSingleton<IApiUserSession, ApiUserPrincipal>(); //CurrentPrincipal实现方式
  10.             //构造对应环境下的UploadSettingOptions信息
  11.             services.Configure<<strong>UploadSettingOptions</strong>>(option =>
  12.             {
  13.                 <strong>SetUploadOptions</strong>(option);
  14.             });
复制代码
  1.         /// <summary>
  2.         /// 构造对应环境下的UploadSettingOptions信息
  3.         /// </summary>
  4.         /// <returns></returns>
  5.         private static UploadSettingOptions SetUploadOptions(UploadSettingOptions option)
  6.         {
  7.             var config = new AppConfig();
  8.             option.AttachmentBasePath = config.AppConfigGet("AttachmentBasePath");
  9.             option.AttachmentUploadType = config.AppConfigGet("AttachmentUploadType");
  10.             option.FtpServer = config.AppConfigGet("FtpServer");
  11.             option.FtpUser = config.AppConfigGet("FtpUser");
  12.             option.FtpPassword = config.AppConfigGet("FtpPassword");
  13.             option.FtpBaseUrl = config.AppConfigGet("FtpBaseUrl");
  14.             return option;
  15.         }
复制代码
就这样,在.net framework的WInform项目启动的时候,我们就完成了文件上传选项参数的读取加载,这样在 FileUploadService 里面的构造函数,就可以获得对应的选项参数信息对象了。
对于.netcore的程序,我们知道它的配置信息是appSettings.json,如下节点所示。
  1.     "<strong>UploadSettingOptions</strong>": {
  2.       "AttachmentBasePath": "", //可指定的存储物理地址,如C:\\Attachment,如果没有配置则默认相对目录。
  3.       "AttachmentUploadType": "", //ftp或空,为空则为普通方式
  4.       "FtpServer": "114.215.106.96", //FTP服务器地址
  5.       "FtpUser": "web2", //FTP账号
  6.       "FtpPassword": "", //FTP密码
  7.       "FtpBaseUrl": "http://www.iqidi.com/ftp"//可以指定为HTTP或者FTP的路径,供下载查看
  8.     }
复制代码
例如对于我们在Web API的初始化选项对象信息,具体加载的代码如下所示。
  1. builder.Services.Configure<UploadSettingOptions>(builder.Configuration.GetSection("UploadSettingOptions"));
复制代码
相对.net framework的处理来说,使用扩展函数来简化了不少。
这样,我们在文件上传处理的服务类中就可以顺利获得对应的配置信息了。
  1.     /// <summary>
  2.     /// 上传附件信息 应用层服务接口实现
  3.     /// </summary>
  4.     public class FileUploadService : MyCrudService<FileUploadInfo,string, FileUploadPagedDto>, IFileUploadService
  5.     {
  6.         //微软引入选项模式,它是用于配置框架服务使用的设置. 选项模式由Microsoft.Extensions.Options NuGet包实现
  7.         //在你需要获得一个选项值时,将 IOptions<TOption> 服务注入到你的类中,使用它的 .Value 属性得到值.
  8.         private readonly UploadSettingOptions _options;
  9.         /// <summary>
  10.         /// 参数化构造,注入上传处理设置信息
  11.         /// </summary>
  12.         /// <param name="options"></param>
  13.         public FileUploadService(IOptions<UploadSettingOptions> options)
  14.         {
  15.             _options = options.Value;
  16.         }
复制代码
我们在使用FTP上传文件的时候,使用了FluentFtp类库实现FTP文件的上传处理的,构建FTP对象的处理代码如下所示。
  1. //使用FluentFTP操作FTP文件
  2. var client = new FtpClient(this.<strong>_options</strong>.FtpServer, this.<strong>_options</strong>.FtpUser, this.<strong>_options</strong>.FtpPassword);
  3. //如果配置指定了端口,则使用特定端口
  4. if (!string.IsNullOrEmpty(this._options.FtpServer) && this._options.FtpServer.Contains(":"))
  5. {
  6.     string port = this._options.FtpServer.Split(':')[1];
  7.     if (!string.IsNullOrEmpty(port))
  8.     {
  9.         client.Port = port.ToInt32();
  10.     }
  11. }
复制代码
上传FTP文件的代码如下所示。
  1.     //确定日期时间目录(格式:yyyy-MM),不存在则创建
  2.     string savePath = string.Format("/{0}-{1:D2}/{2}", DateTime.Now.Year, DateTime.Now.Month, category);
  3.     bool isExistDir = client.DirectoryExists(savePath);
  4.     if (!isExistDir)
  5.     {
  6.         client.CreateDirectory(savePath);
  7.     }
  8.     //使用FTP上传文件
  9.     //避免文件重复,使用GUID命名
  10.     var ext = FileUtil.GetExtension(info.FileName);
  11.     var newFileName = string.Format("{0}{1}", Guid.NewGuid().ToString(), ext);//FileUtil.GetFileName(file);
  12.     savePath = savePath.UriCombine(newFileName);
  13.     var uploaded = await client.UploadAsync(info.FileData, savePath, FtpRemoteExists.Overwrite, true);
  14.     //成功后,写入数据库
  15.     if (uploaded == FtpStatus.Success)
  16.     {
复制代码
 
通过选项参数的方式,我们可以配置参数的IOC处理话,从而实现了参数的灵活配置和读取操作。
在其他业务处理的服务类中,如果涉及到一些需要配置的信息,我们都可以利用这种模式实现参数内容的配置处理。
 
系列文章:
基于SqlSugar的开发框架的循序渐进介绍(1)--框架基础类的设计和使用
基于SqlSugar的开发框架循序渐进介绍(2)-- 基于中间表的查询处理
基于SqlSugar的开发框架循序渐进介绍(3)-- 实现代码生成工具Database2Sharp的整合开发
基于SqlSugar的开发框架循序渐进介绍(4)-- 在数据访问基类中对GUID主键进行自动赋值处理 
基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转
基于SqlSugar的开发框架循序渐进介绍(6)-- 在基类接口中注入用户身份信息接口 
基于SqlSugar的开发框架循序渐进介绍(7)-- 在文件上传模块中采用选项模式【Options】处理常规上传和FTP文件上传
 《基于SqlSugar的开发框架循序渐进介绍(8)-- 在基类函数封装实现用户操作日志记录

来源:https://www.cnblogs.com/wuhuacong/archive/2022/06/13/16370422.html
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

立山

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表