[Abp vNext微服务实践] - 搭建文件存储服务
一、简介#
通过往期的系列文章,我们已经完成了基于ABP框架的授权、基础服务、Business、网关的搭建,并且基于vue-element-admin框架完成了ABP权限管理基础功能和一些常用的后台管理业务功能。本篇文章将持续往期系列,在ABP-MicroService框架中搭建文件存储服务。
二、FileStorage项目搭建#
关于手动搭建ABP空模块项目在往期系列文章和《从0到1搭建ABP微服务系列》中有非常详细的介绍,这里就暂时省略。
三、存储模式#
对于小文件(小于100M)存储可以使用静态文件和数据库两种方式。这两种方式各有优势,静态文件读取速度快、适应场景多,但静态文件路径是公共的,所以比较适合C端系统,或者仅能内网访问的系统。数据库存储更加易于管理,而且二进制存储更加节省空间和保密。
静态文件存储#
.net core中静态文件管理非常方便,只需放在在Host项目的wwwroot文件下就可以轻松管理,如果没有wwwroot文件夹需要创建。
添加UploadController#
在Host项目下创建添加UploadController并添加Upload路由作为文件上传入口,上传接口使用的是.net core官方推荐的IFormFile:
public async Task<ActionResult> Upload([Required]string name, IFormFile file)
{
string uniqueFileName = null;
if (file != null)
{
//限制100M
if (file.Length > 104857600)
{
return new BadRequestObjectResult("上传文件过大");
}
//文件格式
var fileExtension = Path.GetExtension(file.FileName);
if (!pictureFormatArray.Contains(fileExtension))
{
return new BadRequestObjectResult("上传文件格式错误");
}
var size = "";
if (file.Length < 1024)
size = file.Length.ToString() + "B";
else if (file.Length >= 1024 && file.Length < 1048576)
size = ((float)file.Length / 1024).ToString("F2") + "KB";
else if (file.Length >= 1048576 && file.Length < 104857600)
size = ((float)file.Length / 1024 / 1024).ToString("F2") + "MB";
else size = file.Length.ToString() + "B";
string uploadsFolder = Path.Combine(_hostEnvironment.WebRootPath, "Images");
if (!Directory.Exists(uploadsFolder))
{
Directory.CreateDirectory(uploadsFolder);
}
uniqueFileName = Guid.NewGuid().ToString() + fileExtension;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
file.CopyTo(fileStream);
fileStream.Flush();
}
//TODO:文件md5哈希校验
await _fileManager.Create(name, uniqueFileName, fileExtension, "", size, filePath, "/Images/" + uniqueFileName, FileType.Image);
}
return Ok(uniqueFileName);
}
从代码中可以看出文件上传逻辑非常简单,在文件上传成功后将文件信息保存到数据库中就可以轻松实现文件的管理。
接口测试#
vue上传#
使用element-ui组件上传,代码如下:
<el-form-item label="上传">
<el-upload
ref="upload"
:limit="1"
:before-upload="beforeUpload"
:auto-upload="false"
:on-success="handleSuccess"
:on-error="handleError"
:action="storageApi + '/upload?name=' + form.name"
>
<div class="upload">
<i class="el-icon-upload" /> 添加文件
</div>
<div slot="tip" class="el-upload__tip">可上传任意格式文件,且不超过100M</div>
</el-upload>
</el-form-item>
// 上传文件
upload() {
this.$refs.upload.submit();
},
beforeUpload(file) {
let isLt2M = true;
isLt2M = file.size / 1024 / 1024 < 100;
if (!isLt2M) {
this.loading = false;
this.$message.error("上传文件大小不能超过 100MB!");
}
this.form.name = file.name;
return isLt2M;
},
handleSuccess(response, file, fileList) {
this.$notify({
title: "成功",
message: "更新成功",
type: "success",
duration: 2000,
});
this.dialogFormVisible = false;
this.getList();
},
// 监听上传失败
handleError(e, file, fileList) {
this.$notify({
title: e,
type: "error",
duration: 4000,
});
this.loading = false;
},