微服务文件上传下载方案

 

 

具体需求:

文件上传:

(1)  前端使用ant design上传组件完成上传, 直接点击按钮提交,

上传成功后需要服务端返回成功标识;

 

(2) 后端提供独立的服务,

 

(3) 需要判断权限,预留接口

 

(4) 上传下载的表本身与具体业务没有关系

 

(5) 前端先调上传服务,再调业务服务来完成整个业务

 

文件下载:

(1) 前端给后端提供下载标识,由服务端给出下载链接

 

(2) 下载需要断点续传

 

(3) 需要判断权限,预留接口

 

(4) 支持下载计数, 支持tag,

 

(5) 目录结构设计需要考虑

 

(6) 考虑加Job 清理过期文件,预留接口

 

(7) 考虑文件版本设计,预留接口

 

(8) 考虑根据hash排除重复文件,预留接口

 

(9) 考虑需要CND支持,预留接口

 

 

文件导入导出:

 

(1)基于MQ实现导入导出的异步,给出通知(预留接口)

 

(2)文件导入支持excel csv

 

(3) 如果导入文件不存在复杂校验已经数据量小,客户端可以解析文件后发送纯数据给服务端。 

如果存在较复杂业务逻辑校验,文件过大,服务端处理

 

(4)预留接口支持大文件或大批量文件导入导出的性能优化

 

设计:

文件导入设计:

(1)客户端用户发起导入文件请求

(2)业务服务响应请求并接受数据

(3),(5)业务使用Java8 Aync异步调用导入导出公用接口(Jar包形式)

(4)服务端返回前端消息已成功收到文件

(6)对接受到IO流进行解析并转换为DTO数据

    6.1.1,6.1.2, 6.1.3 如果成功转换成DTO,对获取的数据进行后续业务处理,并把导入结果发送消息到通知队列

    6.2.1,6.2.2 如果转换数据失败,调用文件存储服务对导入的文件进行有效期设置并进行存储,最后发送消息到通知队列

(7)通知服务持续监听通知队列

(8)读取消息队列后根据不同的通知类型进行封装

(9)通知相应的客户端

(10)客户端收到通知,提示用户

   

流程图如下:

文件导出设计:

(1)客户端用户发起导出文件请求

(2)业务服务响应请求并接受数据

(3),(4.2)业务使用Java8 Aync初始化需要导出的数据

(4.1)服务端返回前端消息已成功收到文件

(5)导入导出公用接口(Jar包形式)接受到导出数据

(6)根据导出数据生成需要导出的Eexcel元数据

(7)将需要导出的excel数据转换为IO流

(8.1.1)如果业务服务正常获取IO流后直接导出到前端

(8.1.2)调用文件存储服务将导出的文件进行保存

(8.1.3)发出消息到通知队列

(8.2.1)如果业务服务没有正常获取导出的IO流,发出消息到通知队列

(9)通知服务持续监听通知队列

(10)读取消息队列后根据不同的通知类型进行封装

(11)通知相应的客户端

(12)客户端收到通知,提示用户

流程图如下:

导入导出实现:

 创建自定义注解,用以以泛型的方式匹配大部分业务导入导出
@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface IOHeader {

    String headerName() default "";

 int index() default 0;

}

注解中headerName代表导入的标题

            index代表字段在表格中的位置,目前index只对导出起作用

添加类 IOHeaderInfo 包含以下属性 

private String property; //导入导出数据所对应实体中的字段

private String headerName; //导入导出表格中的标题

private Integer index; //导出的字段顺序

添加工具类 IOHeaderUtil 包含方法

public static List<IOHeaderInfo> getIOHeaderInfo(Class<?> clazz)

根据传入的clazz返回IOHeaderInfo类集合, clazz为带有

@IOHeader注解的类

例如

public class InventoryPortationDTO {

    @IOHeader(headerName = "库区编号",index = 0)

    private String areaCode;

 @IOHeader(headerName = "库位编号",index = 1)

    private String locationCode;

 @IOHeader(headerName = "备件编号",index = 2)

    private String sparePartCode;

 @IOHeader(headerName = "备件名称",index = 3)

    private String sparePartName;

 @IOHeader(headerName = "盘点数量",index = 4)

    private Integer quantity;

 @IOHeader(headerName = "备注",index = 5)

    private String remark;
………………

}

文件导入:

/**

 * 文件导入

 * @param outputStream 异常信息输出流 导入的数据不符合clazz字段格式时会把对应信息输出到outputStream中,若格式无误则本参数不做处理

 * @param file 所导入的文件

 * @param clazz 导入文件中数据所对应的带有@IOHeader注解的DTO

 * @return 返回DTO的集合,若导入的数据不符合,则会抛出异常

 * @throws Exception

 */

List<T> fileImport(OutputStream outputStream, MultipartFile file, Class<T> clazz) throws Exception;

调用方式如下所示:

List<WarehousePotationDTO> warehousePotationDTOList = dataPortationService.fileImport(outputStream, multipartFile, WarehousePotationDTO.class);

 

文件导出:
/**

 * 文件导出初始化

 * @param response

 * @param fileName

 */
void initResponse(HttpServletResponse response, String fileName);

本方法会对输出格式做出处理,根据fileName定义输出文件的文件名称

调用方式如下所示:

String fileName = multipartFile.getOriginalFilename();

dataPortationService.initResponse(response, fileName);
 

 

/**

 * 文件导出

 * @param os 所要导出的文件流

 * @param list 带有@IOHeader注解的DTO集合

 * @param clazz 带有@IOHeader注解的DTO

 * @throws Exception

 */

void fileExport(OutputStream os, List<T> list, Class<T> clazz) throws Exception;

调用方式如下所示:

dataPortationService.fileImport(os,list, WarehousePotationDTO.class);

 

 

 

猜你喜欢

转载自blog.csdn.net/ccc7574/article/details/84072682
今日推荐