1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 初识ABP vNext(9):ABP模块化开发-文件管理

初识ABP vNext(9):ABP模块化开发-文件管理

时间:2022-10-27 22:24:49

相关推荐

初识ABP vNext(9):ABP模块化开发-文件管理

点击上方蓝字"小黑在哪里"关注我吧

创建模块

模块开发

应用服务

运行模块

单元测试

模块使用

前言

在之前的章节中介绍过ABP扩展实体,当时在用户表扩展了用户头像字段,用户头像就涉及到文件上传和文件存储。文件上传是很多系统都会涉及到的一个基础功能,在ABP的模块化思路下,文件管理可以做成一个通用的模块,便于以后在多个项目中复用。单纯实现一个文件上传的功能并不复杂,本文就借着这个简单的功能来介绍一下ABP模块化开发的最基本步骤。

开始

创建模块

首先使用ABP CLI创建一个模块:abp new Xhznl.FileManagement -t module --no-ui

创建完成后会得到如下文件:

在主项目中添加对应模块的引用,Application=>Application,Domain=>Domain,HttpApi=>HttpApi 等等。例如:

需要添加引用的项目:Application、Application.Contracts、Domain、Domain.Shared、EntityFrameworkCore、HttpApi、HttpApi.Client

手动添加这些引用比较麻烦,你可以搭建自己的私有NuGet服务器,把模块的包发布到私有NuGet上,然后通过NuGet来安装引用。两种方式各有优缺点,具体请参考自定义现有模块[1],关于私有NuGet搭建可以参考:十分钟搭建自己的私有NuGet服务器-BaGet[2]。

然后给这些项目的模块类添加对应的依赖,例如:

通过上面的方式引用模块,使用visual studio是无法编译通过的:

需要在解决方案目录下,手动执行dotnet restore命令即可:

模块开发

接下来关于文件管理功能的开发,都在模块Xhznl.FileManagement中进行,它是一个独立的解决方案。初学ABP,下面就以尽量简单的方式来实现这个模块。

应用服务

模块开发通常从Domain层实体建立开始,但是这里先跳过。先在FileManagement.Application.Contracts项目添加应用服务接口和Dto。

modules\file-management\src\Xhznl.FileManagement.Application.Contracts\Files\IFileAppService.cs:

publicinterfaceIFileAppService:IApplicationService{Task<byte[]>GetAsync(stringname);Task<string>CreateAsync(FileUploadInputDtoinput);}

modules\file-management\src\Xhznl.FileManagement.Application.Contracts\Files\FileUploadInputDto.cs:

publicclassFileUploadInputDto{[Required]publicbyte[]Bytes{get;set;}[Required]publicstringName{get;set;}}

然后是FileManagement.Application项目,实现应用服务,先定义一个配置类。

modules\file-management\src\Xhznl.FileManagement.Application\Files\FileOptions.cs:

publicclassFileOptions{///<summary>///文件上传目录///</summary>publicstringFileUploadLocalFolder{get;set;}///<summary>///允许的文件最大大小///</summary>publiclongMaxFileSize{get;set;}=1048576;//1MB///<summary>///允许的文件类型///</summary>publicstring[]AllowedUploadFormats{get;set;}={".jpg",".jpeg",".png","gif",".txt"};}

modules\file-management\src\Xhznl.FileManagement.Application\Files\FileAppService.cs:

publicclassFileAppService:FileManagementAppService,IFileAppService{privatereadonlyFileOptions_fileOptions;publicFileAppService(IOptions<FileOptions>fileOptions){_fileOptions=fileOptions.Value;}publicTask<byte[]>GetAsync(stringname){Check.NotNullOrWhiteSpace(name,nameof(name));varfilePath=bine(_fileOptions.FileUploadLocalFolder,name);if(File.Exists(filePath)){returnTask.FromResult(File.ReadAllBytes(filePath));}returnTask.FromResult(newbyte[0]);}[Authorize]publicTask<string>CreateAsync(FileUploadInputDtoinput){if(input.Bytes.IsNullOrEmpty()){thrownewAbpValidationException("Bytescannotbenullorempty!",newList<ValidationResult>{newValidationResult("Bytescannotbenullorempty!",new[]{"Bytes"})});}if(input.Bytes.Length>_fileOptions.MaxFileSize){thrownewUserFriendlyException($"Fileexceedsthemaximumuploadsize({_fileOptions.MaxFileSize/1024/1024}MB)!");}if(!_fileOptions.AllowedUploadFormats.Contains(Path.GetExtension(input.Name))){thrownewUserFriendlyException("Notavalidfileformat!");}varfileName=Guid.NewGuid().ToString("N")+Path.GetExtension(input.Name);varfilePath=bine(_fileOptions.FileUploadLocalFolder,fileName);if(!Directory.Exists(_fileOptions.FileUploadLocalFolder)){Directory.CreateDirectory(_fileOptions.FileUploadLocalFolder);}File.WriteAllBytes(filePath,input.Bytes);returnTask.FromResult("/api/file-management/files/"+fileName);}}

服务实现很简单,就是基于本地文件系统的读写操作。

下面是FileManagement.HttpApi项目,添加控制器,暴露服务API接口。

modules\file-management\src\Xhznl.FileManagement.HttpApi\Files\FileController.cs:

[RemoteService][Route("api/file-management/files")]publicclassFileController:FileManagementController{privatereadonlyIFileAppService_fileAppService;publicFileController(IFileAppServicefileAppService){_fileAppService=fileAppService;}[HttpGet][Route("{name}")]publicasyncTask<FileResult>GetAsync(stringname){varbytes=await_fileAppService.GetAsync(name);returnFile(bytes,MimeTypes.GetByExtension(Path.GetExtension(name)));}[HttpPost][Route("upload")][Authorize]publicasyncTask<JsonResult>CreateAsync(IFormFilefile){if(file==null){thrownewUserFriendlyException("Nofilefound!");}varbytes=awaitfile.GetAllBytesAsync();varresult=await_fileAppService.CreateAsync(newFileUploadInputDto(){Bytes=bytes,Name=file.FileName});returnJson(result);}}

运行模块

ABP的模板是可以独立运行的,在FileManagement.HttpApi.Host项目的模块类FileManagementHttpApiHostModule配置FileOptions:

修改FileManagement.HttpApi.Host和FileManagement.IdentityServer项目的数据库连接配置,然后启动这2个项目,不出意外的话可以看到如下界面。

FileManagement.HttpApi.Host:

FileManagement.IdentityServer:

现在你可以使用postman来测试一下File的2个API,当然也可以编写单元测试。

单元测试

更好的方法是编写单元测试,关于如何做好单元测试可以参考ABP源码,下面只做一个简单示例:

模块使用

模块测试通过后,回到主项目。模块引用,模块依赖前面都已经做好了,现在只需配置一下FileOptions,就可以使用了。

目前FileManagement.Domain、FileManagement.Domain.Shared、FileManagement.EntityFrameworkCore这几个项目暂时没用到,项目结构也不是固定的,可以根据自己实际情况来调整。

最后

本文的模块示例比较简单,只是完成了一个文件上传和显示的基本功能,关于实体,数据库,领域服务,仓储之类的都暂时没用到。但是相信可以通过这个简单的例子,感受到ABP插件式的开发体验,这是一个好的开始,更多详细内容后面再做介绍。本文参考了ABP blogging模块的文件管理,关于文件存储,ABP中也有一个BLOB系统可以了解一下。

参考资料

[1]

自定义现有模块:https://docs.abp.io/zh-Hans/abp/latest/Customizing-Application-Modules-Guide

[2]

十分钟搭建自己的私有NuGet服务器-BaGet:/xhznl/p/13426918.html

如果本文对您有用,

不妨点个“”或者转发朋友圈支持一下

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。