需求:导出一个共享文档校验结果.zip压缩包,里面有二个子文件,一个是xml文件,一个是excel的xls文件。前者的xml文件简单直接内容string转字节输出流生成一个后缀为xml的子文件流,后者的excel文件则需要将excel文件的字节流转为一个子文件流。
核心代码
//进行导出下载
String zipName = "共享文档校验结果" + DateUtils.getInstance().dateToStr(new Date(), CommonConstant.YYYYMMDDHHMMSS) + ".zip";
setAttachmentResponseHeader(response, zipName);
try(ZipOutputStream out = new ZipOutputStream(response.getOutputStream())){
for (BatchExportZipDTO batchExportZipDTO : batchExportZipDTOS) {
//导出校验Xml
downloadVerifyCdaXml(batchExportZipDTO.getIcQvVerifyXml(), out);
//导出校验结果
downloadVerifyDetails(batchExportZipDTO.getIcQvVerifyDetailVOS(), batchExportZipDTO.getIcQvVerifyVO(), out);
}
}catch(Exception e){
logger.error("共享文档批量导出失败:{}", ExceptionUtil.getExceptionMessage(e));
throw e;
}
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
String percentEncodedFileName = percentEncode(realFileName);
StringBuilder contentDispositionValue = new StringBuilder();
contentDispositionValue.append("attachment; filename=").append(percentEncodedFileName).append(";").append("filename*=").append("utf-8''").append(percentEncodedFileName);
response.setHeader("Content-disposition", contentDispositionValue.toString());
}
public static String percentEncode(String s) throws UnsupportedEncodingException {
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20");
}
下面的二个方法是对response消息头的处理,将定义的zip名称放入response中
再将处理后的response转为ZipOutputStream输出流out,再通过下面的二个方法在out其中存入二个子目录。
downloadVerifyCdaXml:这个方法也是定义了一个子文件的名称,然后将子名称放入ZipEntryzip条目中,再将条目放入out流中,再往out中写入东西。
/**
* 导出校验Xml
* @param icQvVerifyXml icQvVerifyXml
* @param out out
* @throws Exception Exception
*/
private void downloadVerifyCdaXml(ICQvVerifyXml icQvVerifyXml, ZipOutputStream out) throws Exception{
if (icQvVerifyXml != null){
if (StringUtils.isNotBlank(icQvVerifyXml.getVerifyXmlData())){
//组装文件名
String fileName = icQvVerifyXml.getVerifyXmlName() + "." + icQvVerifyXml.getVerifyXmlSuffix();
ZipEntry entry = new ZipEntry(fileName);
out.putNextEntry(entry);
try (
InputStream ins = new ByteArrayInputStream(icQvVerifyXml.getVerifyXmlData().getBytes(StandardCharsets.UTF_8));
BufferedInputStream bis = new BufferedInputStream(ins)) {
byte[] buffer = new byte[1024];
int i = bis.read(buffer);
while (i != -1) {
out.write(buffer, 0, i);
out.flush();
i = bis.read(buffer);
}
}
out.closeEntry();
}
}
}
downloadVerifyDetails:最关键在于wb.write(outputStream);将生成的Workbook流写入out中,定于子目录名称什么的和上面一样。最终都是将流写入out中
/**
* 导出校验结果
* @param icQvVerifyDetailVOS icQvVerifyDetailVOS
* @param icQvVerifyVO icQvVerifyVO
* @param out out
* @throws Exception Exception
*/
private void downloadVerifyDetails(List<ICQvVerifyDetailVO> icQvVerifyDetailVOS, ICQvVerifyVO icQvVerifyVO, ZipOutputStream out) throws Exception{
if (icQvVerifyDetailVOS.size() > 0){
ZipEntry entry = new ZipEntry(icQvVerifyVO.getVerifyXmlName() + "-" + icQvVerifyVO.getCdaNo() + ".xls");
out.putNextEntry(entry);
ICQvExcelUtils<ICQvVerifyDetailVO> excelUtil = new ICQvExcelUtils<ICQvVerifyDetailVO>(ICQvVerifyDetailVO.class);
excelUtil.init(icQvVerifyDetailVOS, "校验结果列表", Excel.Type.EXPORT);
excelUtil.exportExcelNotCloseOut(out);
out.closeEntry();
}
}
excelUtil.init是excel工具类的一个生成excel初始化的操作,下面的excelUtil.exportExcelNotCloseOut(out);是手写的也继承excelUilt类的将wb写入out流的方法。
public class ICQvExcelUtils<T> extends ExcelUtil<T> {
/**
* 导出不关闭流
* @param outputStream outputStream
*/
public void exportExcelNotCloseOut(OutputStream outputStream)
{
try
{
// 取出一共有多少个sheet.
double sheetNo = Math.ceil(list.size() / sheetSize);
for (int index = 0; index <= sheetNo; index++)
{
createSheet(sheetNo, index);
// 产生一行
Row row = sheet.createRow(0);
int column = 0;
// 写入各个字段的列头名称
for (Object[] os : fields)
{
Excel excel = (Excel) os[1];
this.createCell(excel, row, column++);
}
if (Excel.Type.EXPORT.equals(type))
{
fillExcelData(index, row);
addStatisticsRow();
}
}
wb.write(outputStream);
}
catch (Exception e)
{
log.error("导出Excel异常{}", e.getMessage());
}
finally
{
if (wb != null)
{
try
{
wb.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
}
}
}