采用 ABP BLOB Storing 进行文件上传管理

类别:技术 日期:2023-06-18 评论:0

最近在用 ABP vNex 写一个服务端后台,涉及到实体文件上传到服务器,并支持查找、删除等常规操作的需求。

第一反应是用 .NET Core 的 Controller 自己实现,要写不少操作逻辑,后来想到自己都用上了ABP 框架帮我实现其他业务需求,为何不试试看 ABP 有没有类似的类库呢?

搜索之下发现了 ABP 果然有现成的类库 BLOB String ,作为一个成熟类库,包含常规的增删改查操作是基本的,我看了一下官方文档,除了对自有服务器文件管理系统的支持,还封装好了对 Azure、Aws、阿里云等云厂商的操作接口,果然是使用现有框架能事半功倍。

下面记录一下我自己的配置使用过程,其实官网更好,我自己写一篇,只是为了加深印象,如果能对其他开发者有一点点的帮助,那是更好了。

一、安装依赖

这里和其他ABP的官方类库一样的引用方法,可以通过 ABP CLI 的 abp add-package Volo.Abp.BlobStoring 命令来执行安装,也可以通过 VS 的 nuGet 包管理器进行可视化安装。我这里使用的是自有服务器,所以还安装了 Volo.Abp.BlobStoring.FileSystem 二级包,如果是要用其他云商的接口,安装相应的包即可。

在后面的使用中发现其实只安装 Volo.Abp.BlobStoring.FileSystem 这个二级包就可以了。

二、配置容器

这个文件管理类库是以容器 Container 概念管理文件的,一个系统中可以有多个 Container ,给分别起名字配置即可。

起名字配置的方法是创建一个简单的类,在名为 BlobContainerName 的 attribute 中配置名字,比如要配置一个存放项目pdf的容器.

using Volo.Abp.BlobStoring;
namespace AbpDemo
{
    [BlobContainerName("project-pdf")]
    public class ProjectPdfContainer
    {
        
    }
}

这样配置后,文件上传到服务器上的时候,服务器上会自动创建一个名为”project-pdf“的文件夹存放文件。

因为我使用的是自有服务器存放文件,所以还要配置这个容器服务器的根路径,这个在我们要使用的module文件的 ConfigureServices 方法中注入配置,配置时候注入的类型是刚才定义的容器类名。

Configure<AbpBlobStoringOptions>(options =>
{
    options.Containers.Configure<FileBlobContainer>(container =>
    {
        container.UseFileSystem(fileSystem =>
        {
            fileSystem.BasePath = "D:\\ProjectFiles";
        });
    });
});

这个配置方法有个”强大“的地方是可以配置服务器上的任意路径,这比用 ASP.NET Core Controller 自己实现方法部署在IIS上的时候方便很多,因为由于IIS权限的问题,程序只能方便地管理 wwwroot 文件夹下的路径,尤其是在删除和下载文件功能的具体实现上。

三、实现服务

框架容器类库中几个现有的接口方法足以满足新增、删除和下载的功能。

新增

public async Task SaveFileAsync(byte[] bytes)
{
    var blobName = "myName";
    await _blobContainer.SaveAsync(blobName, bytes);
}

获取(下载)

public async Task<byte[]> GetFileAsync(blobName)
{
    return await _blobContainer.GetAllBytesOrNullAsync(blobName);
}

删除

public async Task<byte[]> GetFileAsync(blobName)
{
    return await _blobContainer.DeleteAsync(blobName);
}

这些封装好的方法还支持子文件夹的操作,如果要将文件存到文件夹中,只需要载入参的文件名 blobName 前面加上文件夹名称和斜杠/”即可,系统会自动在project-pdf”下面再创建一个文件夹再存放文件,获取和删除时候亦然。

四、前端调用

我前端是用 vue+Element 实现的,上传功能用的是 Element 自带的 el-upload 组件,在使用时候将组件的 action 参数配置为空,然后停用 auto-upload 自动上传属性。

自定义一个 formData 变量,将组件选取到的文件 raw 赋给 formData 的 file 键上,然后将 formData 作为 post 请求方法的  data 参数调用即可。

const formData = new FormData()
formData.append('file', this.fileToUpload.raw)
// 上传文件
export function uploadFile(data) {
  return request({
    url: '/api/app/project-file/upload-file',
    method: 'post',
    data: data,
  })
}

获取下载的操作在前端要有个一字节流转成文件的操作。因为默认的前端框架是返回json格式的,而上面 ABP BLOB Storing 类库返回的是字节流 blob 格式的,所以我单独封装了一个请求方法。

import axios from 'axios'
export function downloadFile(config) {
  return new Promise((resolve, reject) => {
    axios({
      url: config.url,// 请求地址
      method: 'get',
      params: config.pa, //传给后台的参数,文件名或者包含文件夹的路径
      responseType: 'blob'// 表明返回服务器返回的数据类型
    }).then(res => {
      resolve(res)
    }).catch(err => {
      reject(err);
    });
  });

在vue组件的method中使用下面的方法即可实现文件的下载。

downloadFile(pConfig).then(res => {
	let blob = new Blob([res.data])
	if ('download' in document.createElement('a')) { // 不是IE浏览器
	  let url = window.URL.createObjectURL(blob)
	  let link = document.createElement('a')
	  link.style.display = 'none'
	  link.href = url
	  link.setAttribute('download', 'myName')
	  document.body.appendChild(link)
	  link.click()
	  document.body.removeChild(link) // 下载完成移除元素
	  window.URL.revokeObjectURL(url) // 释放掉blob对象
	} else { // IE 10+
	  window.navigator.msSaveBlob(blob,'myName')
	}
	}).catch(err => {
	this.$message.error("获取下载文件失败" + err)
})

上面核心步骤是从后台给的数组转成blob,然后使用 window.URL.createObjectURL(blob)  获取文件下载路径。

留言评论

天上的神明和星辰,人间的艺术与真纯,
我们所敬畏和景仰的,莫过于此。

推荐文章
软件作品
微信公号
  • 足球Plus微信公众号
最新留言
友情链接
推荐文章

天上的神明和星辰,人间的艺术与真纯,
我们所敬畏和景仰的,莫过于此。

软件作品
最新留言