微服务平台在开发网关时没考虑小文件的上传和下载,而是直接由交文件服务处理,返回访问文件的URL给业务。
现在业务需要上传导入和导出下载,因所有后端服务接口请求必须走网关,上传和下载就必须经过文件服务来处理。
上传
由页面直接请求文件服务上传文件,文件服务返回访问文件的URL或GUID给业务。
导入
前端请求文件服务上传文件,文件服务返回URL或GUID,前端拿到 URL或GUID和其它参数一起请求业务后端,业务后端下载文件执行导入操作。
导出
将业务数据写出到文件(临时文件),读取文件上传到文件服务,拿到返回的 URL 或 GUID去下载。
需求
导出订单数据到 Excel 表
实现
导出使用 EasyPoi 工具,快捷方便。
- 添加依赖 - <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>4.1.0</version> </dependency>
- 与 Excel 列名对应的实体类 - @Data @Accessors(chain = true) public class OrderExportBO { /** * 下单时间 */ @Excel(name = "下单时间", width = 20) private String createdTime; /** * 送餐日期 */ @Excel(name = "配送日期", width = 20) private String deliveryDate; /** * 收件人 */ @Excel(name = "姓名", width = 15) private String consignee; /** * 手机号 */ @Excel(name = "手机号", width = 15) private String mobile; /** * 地址 */ @Excel(name = "地址", width = 20) private String address; /** * 金额 */ @Excel(name = "金额", width = 10) private BigDecimal totalFee; /** * 备注 */ @Excel(name = "备注", width = 30) private String remark; }
- 业务实现 - @Service public class ExportServiceImpl implements ExportService { private static final Logger logger = LogManager.getLogger(ExportServiceImpl.class); @Autowired private RestTemplate restTemplate; @Autowired private FileServerProperties fileServerProperties; /** * @desc: 导出订单 * @param: [orderVO] */ @Override public ResponseModel<?> exportOrder(OrderVO orderVO) { // 查询订单数据 List<BzOrder> orderList = this.queryOrderList(orderVO); // 将订单数据包装成要导出的数据 List<OrderExportBO> exportList = this.wrapExportData(orderList); // EasyPoi导出 ExportParams exportParams = new ExportParams(); exportParams.setType(ExcelType.XSSF); Workbook workbook = ExcelExportUtil.exportExcel(exportParams, OrderExportBO.class, exportList); // 字节数组输出流 ByteArrayOutputStream out = new ByteArrayOutputStream(); ResponseModel<?> responseModel = null; try { workbook.write(out); out.flush(); out.close(); workbook.close(); // 字节数组输入流 ByteArrayInputStream bio = new ByteArrayInputStream(out.toByteArray()); // 创建临时文件 File file = File.createTempFile("导出订单信息", ".xlsx"); FileUtils.copyInputStreamToFile(bio, file); // 上传 responseModel = this.uploadFile(file); } catch (IOException e) { e.printStackTrace(); logger.error("导出订单信息异常:{}", e.getMessage()); throw new BusinessException(e); } return responseModel; } /** * @desc: 上传文件 * @param: [file] */ private ResponseModel<?> uploadFile(File file) { // 设置请求头 HttpHeaders headers = new HttpHeaders(); // MediaType type = MediaType.parseMediaType(MediaType.MULTIPART_FORM_DATA_VALUE); // headers.setContentType(MediaType.MULTIPART_FORM_DATA); MediaType type = MediaType.parseMediaType("multipart/form-data"); headers.setContentType(type); FileSystemResource resource = new FileSystemResource(file); // 设置请求体,注意是LinkedMultiValueMap MultiValueMap<String, Object> form = new LinkedMultiValueMap<>(); form.add("file", resource); form.add("serverName", fileServerProperties.getServerName()); // 用HttpEntity封装整个请求报文 HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(form, headers); // RestTemplate ResponseModel<?> response = restTemplate.postForObject(fileServerProperties.getUrl(), files, ResponseModel.class); return response; } }
- RestTemplate 配置 - @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { RestTemplate template = new RestTemplateBuilder() .setConnectTimeout(Duration.ofMillis(30000)) .setReadTimeout(Duration.ofMillis(30000)) .build(); return template; } }
- 属性配置 - @Data @Accessors(chain = true) @Configuration @ConfigurationProperties(prefix = "file.server") public class FileServerProperties { /** * url */ private String url; /** * serverName */ private String serverName; }- 配置文件属性: - #===========File Server============ file.server.url=http://file-server.domain.com/upload file.server.serverName=xxxxxxxxxx
压缩
压缩打包上传
ByteArrayOutputStream zipos = new ByteArrayOutputStream(61858764);//设置大小为60M
ZipOutputStream zos = new ZipOutputStream (zipos) ;//创建压缩流,初始化一个输出流缓存区
for(Entry<String, JSONObject> entry : mapData.entrySet()){
    String key = entry.getKey();
    JSONObject jsonVal = entry.getValue();
    OrderMonitorExcelViewSvc orderMonitorExcelView = new OrderMonitorExcelViewSvc(jsonVal);
    try {
        orderMonitorExcelView.outputToFile("orderMonitorExport_"+key);
    } catch (Exception e1) {
        logger.info(e1);
    }
    HSSFWorkbook workbook = orderMonitorExcelView.getWorkbook();
    ByteArrayOutputStream os = new ByteArrayOutputStream(61858764);//设置大小为60M
    try {
        workbook.write(os);
        //创建一个压缩文件里的名称
        ZipEntry zipEntry = new ZipEntry("订单监控查询"+key+".xls");
        System.out.println(os.size());
        zipEntry.setSize(os.size());
        zipEntry.setCompressedSize(os.size());
        zos.putNextEntry(zipEntry);
        os.writeTo(zos);
        zos.closeEntry();      
        os.close();
    } catch (IOException e) {
        logger.info("写入ZipOutputStream异常");
    }
}
try {
    zos.close();//注意关闭流的顺序,在上传oss之前必须关闭流否则下载解压的时候会报“文件末端错误”的问题
    zipos.close();
    ByteArrayInputStream zipis = new ByteArrayInputStream(zipos.toByteArray());
    @SuppressWarnings("deprecation")
    int rel = cpsdCoralStorage.uploadFile("order_monitor_data/"+batchno,zipis);
    if(rel==0){
        orderMonitorDao.updateDownloadBatch("0", batchno);
    }
    zipis.close();
} catch (IOException e) {
    logger.info("上传oss失败");
    logger.info("关闭压缩流异常"+e);
}
下载压缩文件
@RequestMapping(value = { "downloadExport" })
public void downloadExport(HttpServletRequest request, HttpServletResponse response,
                           @RequestParam(value = "batchno", required = true) String batchno) throws IOException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
    String formatDate = sdf.format(new Date());
    String pathName = "order_monitor_data/" + batchno;
    String srcFileName = "导出结果" + formatDate + ".zip";
    InputStream is = cpsdCoralStorage.downloadFile(pathName);
    try {
        response.setHeader("content-disposition",
                           "attachment;filename=" + URLEncoder.encode(srcFileName, "utf-8"));
        OutputStream out = response.getOutputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int temp =0;
        while((temp=is.read())!=-1){ // 读取内容  
            baos.write(temp);
        }
        byte[] xlsBytes = baos.toByteArray();
        out.write(xlsBytes);
        out.flush();
        out.close();
    }
    catch (FileNotFoundException e) {
        logger.logException(e);
    }
    catch (IOException e) {
        logger.logException(e);
    }
}
参考
更多内容请访问:IT源点
注意:本文归作者所有,未经作者允许,不得转载
 
 
            