Skip to content

上传下载

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

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

基本流程

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

上传

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

upload

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

提示

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

绑定

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

bind

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

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

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

查询

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

注解

为方便使用,我们提供了声明式的文件绑定和文件查询实现。使用时将其添加到控制器服务方法上即可。

@BoundFile

绑定文件。

参数

名称类型说明
businessCodeString业务模块标识,用来区分一个表单多个上传组件的情况。
businessIdString业务 id 表达式,执行结果必须为 String。
idsString文件 id 表达式,支持 String 和 List<String>。

提示

关于 businessId,如果为新增数据,则应该从方法返回值(声明为 result)中获取;编辑数据时则应该从方法入参中获取。

示例

下面给出一个使用示例。

java
@ApiOperation("添加")
@PostMapping
@BoundFile(businessCode = "'default'", businessId = "#result.body", ids = "#input.manual")
public AjaxResult add(@Valid @RequestBody FooBizAddDto input) {
    String id = service.add(input);
    return AjaxResult.success("成功", id);
}

@ApiOperation("修改")
@PutMapping
@BoundFile(businessCode = "'default'", businessId = "#input.id", ids = "#input.manual")
public AjaxResult edit(@Valid @RequestBody FooBizEditDto input) {
    service.edit(input);
    return AjaxResult.success();
}
java
public class FooBizAddDto
{
    private string manual;
    // 省略其它属性和 get/set
}
java
public class FooBizEditDto
{
    private string id;
    private string manual;
    // 省略其它属性和 get/set
}

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

  • 新增时,从方法返回值(声明为 result)的 body 中获取业务id。
  • 编辑时,从方法参数表中的 input 参数获取业务id。

@GetBoundFile

返回关联文件。

接口约定

业务关联的文件由框架自动写入返回数据,前提是实现特定的接口。

  1. SingleGetBoundFileService 接口

    • 实现 getBusinessId(),返回业务 id,以查询关联的文件。
    • 实现 getBusinessCode(), 返回业务模块名,区分多个上传组件。
    • 实现 setBoundFiles(List<FileCloudStorageSimpleVo> vos),接收传入的文件信息。
  2. MultiGetBoundFileService 接口

    • 实现 getBusinessId(),返回业务 id,以查询关联的文件。
    • 实现 setBoundFilesByMap(Map<String, List<FileCloudStorageSimpleVo>> voMap),接收传入的文件信息。Map 的键为 BusinessCode。

示例

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

java
@GetMapping("/{id}")
@GetBoundFile
public AjaxResult<FooBizVo> detail(@PathVariable String id) {
    FooBizVo vo = service.getById(id);
    return AjaxResult.success(vo);
}
java
public class FooBizVo implements MultiGetBoundFileService
{
    private String id;
    private Map<String, List<FileCloudStorageSimpleVo>> manualFiles = Collections.emptyMap();

    @Override
    public String getBusinessId() {
        return id;
    }

    @Override
    public void setBoundFilesByMap(Map<String, List<FileCloudStorageSimpleVo>> voMap) {
        this.manualFiles = voMap;
    }
}

上例中,通过注解声明要将关联的文件信息添加到结果对象中,关键在于 Vo 类对接口的实现。

提示

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