Skip to content

文件管理 v3.1.1+

这里讲的文件特指业务表单上传的附件,它们都保存在对象存储服务器上。为了减少冗余文件,我们需要记录每个文件的使用情况,这样才能定期清理掉未使用的文件。同时,将文件处理逻辑统一实现,可以精简业务代码,减少开发人员工作。

框架提供了标准功能,用来处理文件记录、文件绑定(标记使用)、文件查询等需求。

基本流程

为方便理解后续内容,我们先来看一下文件上传和处理的基本流程,确保大家处在同一认识基点。

上传

现在我们推荐使用前端直连对象存储服务(下文以 MinIO 代替)的形式上传文件,减少中转服务器和网络压力,尤其是上传文件体积较大的情况。

upload

如上图所示,前端需要先请求预签名的 MinIO 上传地址,然后直接向 MinIO 服务上传文件。上传成功后,向后端请求创建文件记录。

提示

具体操作开发人员不必关心,由上传组件统一处理。调用接口分别为 /api/file-cloud-storage/sign/upload/api/file-cloud-storage/add

绑定

绑定即将文件标记为使用中状态,这时文件与特定的业务数据关联,成为与其相关的附件。

bind

如上图所示,后端程序根据表单传入的必要信息进行文件绑定。

  • FileId 文件记录id,在上一步创建文件记录时返回。
  • BusinessId 业务数据的唯一标识
  • BusinessCode 由开发人员定义,用以表示表单内的上传来源。 想象一下,如果表单中有多个地方需要上传文件,那么在回显时就必须要知道文件应该显示在哪个位置。

图上还展示了一个未被使用的文件 0c952b,未来可以根据这些记录统一清理掉 MinIO 上未使用的文件。

查询

在展示业务表单时,可以从文件管理服务获取关联的附件信息。这时仅需要传入 BusinessId,一次性取得关联的所有附件。

特性标签

为方便使用,我们提供了基于特性(Attribute)的文件绑定和文件查询实现。使用时将其添加到控制器方法上即可。

BindBizFileAttribute

绑定文件。

参数

名称类型说明
bizModeBindFileBizMode业务操作模式,新增或编辑。
bizIdExpressionString业务 id 表达式,执行结果必须为 string。
filesExpressionString文件信息表达式,执行结果必须为 List<FileStorageBindDto>。

提示

bizMode 决定了从哪里获取业务 id。如果为新增模式,则从方法返回值中获取;反之则从方法入参中获取,同时还会尝试先解绑已关联的文件。

表达式执行的上下文对象为入参或返回值,分别挂载在 p 对象和 r 对象下。

注意

表达式严格区分大小写,更多信息请查看表达式引擎

示例

下面给出一个使用示例。

csharp
[HttpPost]
[BindBizFile(BindFileBizMode.Create, "r.Body", "p.dto.Files")]
public Result<string> AddFoo(FooBizAddDto dto)
{
    // 等同于 Result<string>.Success("001", "成功"),v3.0.0+ 可用。
    return "001".ToResult();
}

[HttpPut]
[BindBizFile(BindFileBizMode.Edit, "p.dto.Id", "p.dto.Files")]
public Result EditFoo(FooBizAddDto dto)
{
    return Result.Success();
}
csharp
public class FooBizAddDto : FileStorageBindBaseDto
{
    public string Name { get; set; }
}
csharp
public class FooBizEditDto : FileStorageBindBaseDto
{
    public string Id { get; set; }
    public string Name { get; set; }
}

上例中,通过特性标签声明了将传入的文件信息绑定到业务id。

  • 新增时,从方法返回值(框架定义为 r)的 Body 中获取业务id。
  • 编辑时,从方法参数表(框架定义为 p)中的 dto 参数获取业务id。

同时,Dto 类从框架内置类 FileStorageBindBaseDto 继承了 Files 属性来接收传入的文件信息, 因此表达式为 p.dto.Files。 当然,也可以根据实际需要直接在 Dto 声明其它属性来接收文件信息,但类型必须为 List<FileStorageBindDto>。

前端数据格式

FileStorageBindDto 实际上规定了前端传入的数据格式,示例如下。

javascript
{
  // 其它业务字段省略
  files: [
    {bizCode: 'foobiz-field1', fileIds: ['19203489231', '192049392018']},
    {bizCode: 'foobiz-field2', fileIds: ['19203489231']}
  ]
}

ResponseBizFileAttribute

返回关联文件。方法返回值必须继承 FileStorageBaseVo

参数

名称类型说明
bizIdExpressionString业务id表达式,执行结果必须为 string。

注意

此处仅支持从返回结果中获取业务 id。

示例

下面是一个获取已绑定文件列表的示例。

csharp
[HttpGet]
[ResponseBizFile("r.Body.Id")]
public Result<FooBizVo> GetDetail()
{
    FooBizVo foo = service.Get();
    return foo.ToResult();
}
csharp
public class FooBizVo : FileStorageBaseVo
{
    public string Id { get; set; }
    public string Name { get; set; }
}

上例中,通过特性标签声明要将关联的文件信息添加到结果对象中。 此时仅需要指定业务 id,与之相关的所有文件都会被返回。

FooBizVo 类从 FileStorageBaseVo 继承了 BizFiles 属性,承载查询到的关联文件信息。

提示

查询文件信息时,会刷新文件访问地址的有效期。最长有效期为 1 天。

前端数据格式

为方便前端使用,文件数据按 BusinessCode 组织为对象形式。示例如下。

json
{
  "code": 0,
  "msg": "操作成功",
  "body": {
    // 其它业务字段省略
    "bizFiles": {
      "foobiz-field1": [
        {
          "id": "1088667670116564992",
          "fileName": "test001.jpg",
          "businessCode": "foobiz-field1",
          "url": "http://foo.minio/static/00535a6618184740b4643fae65379016.jpg?signature="
        },
        {
          "id": "1088667708173582336",
          "fileName": "test002.jpg",
          "businessCode": "foobiz-field1",
          "url": "http://foo.minio/static/009a23236e914cb581ddae30c6e6f011.jpg?signature="
        },
        {
          "id": "1088667754042490880",
          "fileName": "test003.jpg",
          "businessCode": "foobiz-field1",
          "url": "http://foo.minio/static/0101334fdfd140fcae93ef7611e621a3.png?signature="
        }
      ],
      "foobiz-field2": [
        {
          "id": "1088667769743867904",
          "fileName": "test004.jpg",
          "businessCode": "foobiz-field2",
          "url": "http://foo.minio/static/012c7c99c71f48b8b349edc0c55bef7c.jpg?signature="
        }
      ]
    }
  }
}

服务调用

除了特性标签,也可以手动调用文件管理服务的绑定、删除、查询方法。具体请查看 FileStorageService 源码。

附录

FileStorageBindBaseDto

csharp

public class FileStorageBindBaseDto
{
    public List<FileStorageBindDto> Files { get; set; }
}

FileStorageBindDto

csharp

public class FileStorageBindDto
{
    public string BizCode { get; set; }
    public List<string> FileIds { get; set; }
}

FileStorageBaseVo

csharp
public class FileStorageBaseVo
{
    public Dictionary<string, List<FileStorageSimpleVo>> BizFiles { get; set; }
}

FileStorageSimpleVo

csharp
public class FileStorageSimpleVo
{
    /// <summary>
    /// 文件ID
    /// </summary>
    public string Id { get; set; }

    /// <summary>
    /// 原始文件名
    /// </summary>
    public string FileName { get; set; }

    /// <summary>
    /// 业务标识码
    /// </summary>
    public string BusinessCode { get; set; }

    /// <summary>
    /// 文件地址
    /// </summary>
    public string Url { get; set; }
}