微服务平台在开发网关时没考虑小文件的上传和下载,而是直接由交文件服务处理,返回访问文件的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源点
注意:本文归作者所有,未经作者允许,不得转载