web端多個excel的生成和打包成zip檔案
阿新 • • 發佈:2019-01-31
需求
伺服器生成資料,但是資料超過一定行需要分成多個excel,並且打包成zip供web端下載。
分析
- 已知:
- 可以生成excel檔案
- 無法生成zip檔案包
- 需要做的事情
- 實現多個檔案的打包,生成zip檔案。
- 從一個excel檔案直接生成到生成多個檔案。
- 未知問題需要解決
流程
public static void example2() throws IOException {
//檔案流的目的,這裡可以用outpuStream快取
File file = new File("D:\\f.zip");
FileOutputStream fos = new FileOutputStream(file);
//指定zip流的輸出目的點
ZipOutputStream zip = new ZipOutputStream(fos);
//包增加一個檔案條目,初始化輸入名稱
ZipEntry entry = new ZipEntry("test.txt");
zip.putNextEntry(entry);
//輸入位元組流作為檔案條目的來源
zip.write("a simple txt".getBytes());
//同上
ZipEntry entry2 = new ZipEntry("test2.txt");
zip.putNextEntry(entry2);
zip.write("a simple file2".getBytes());
//關閉檔案條目的輸入點
zip.closeEntry();
//關閉zip流
zip.close();
}
main 函式如下
public static void main(String[] args) {
try {
example2();
System.out .println("succeed!");
} catch (IOException e) {
e.printStackTrace();
}
}
外加條件:已經可以在web端生成了excel檔案,方法函式如下:
public ResponseEntity<byte[]> downloadInvoiceAndPackingList(@PathVariable("shipmentId") @NotNull Long shipmentId) {
String filename = "xxxx.xlsx";
String suffix = ".xlsx";
StringBuilder downloadFileName = new StringBuilder("xxxx");
try (InputStream input = EnvUtils.isDevFromSystem() ? //模板輸入流
this.getClass().getClassLoader().getResourceAsStream(
WmsConstant.WMS_TEMPLATE_ROOT + filename) :
new FileInputStream(WmsPathUtil.getTemplateReportPath().resolve(filename).toFile());
//結果輸出流
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
Context context = new Context();
//*******業務程式碼
//jxlsHelper渲染處理xlxs,input+ context ---->outPut
JxlsHelper.getInstance().processTemplate(input, output, context);
//返回請求為位元組流
return genResponseEntityFromBytes(MediaType.APPLICATION_OCTET_STREAM,
downloadFileName.toString(), output.toByteArray());
} catch (Exception e) {
throw new CodeException(CodeConstant.Common.DOWNLOAD_FILE_ERROR, e);
}
}
我們已知過程中有excel的輸出流生成,返回web段的是處理後輸出流生成的位元組流。
可能存在的方案
根據 1. 解決2.1 打包問題 我們有如下解決方案:
- 在伺服器生成快取資料夾,把excel先生成放在資料夾下
- 讀取路徑下的所有的excel檔案生成zip檔案流
- zip流生成位元組流返回到web端
這是一個解決方案,但這個方案有點小傻,做了太多的多餘事情。在結合外加條件,可以知道在生成現有excel的過程中,我們已經有檔案流生成了,那麼我們可以直接把生成的流,載入到zipOutputStream流中就可以了
//這是zos的輸出流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(bos);
//迴圈
for (xxx:xxxxx) {
//****業務程式碼
//定義檔案的輸入流
InputStream input = EnvUtils.isDevFromSystem() ?
this.getClass().getClassLoader().getResourceAsStream(
WmsConstant.WMS_TEMPLATE_ROOT + filename) :
new FileInputStream(WmsPathUtil.getTemplateReportPath().resolve(filename).toFile());
//定義檔案的輸出流,但是這是作為zip流的一部分
ByteArrayOutputStream output = new ByteArrayOutputStream();
//用jxlsHelper來處理xlxs輸出了流
JxlsHelper jxlsHelper = new WmsJxlsHelper();
jxlsHelper.processTemplate(input, output, context);
//命名檔案
zos.putNextEntry(new ZipEntry(channelName + ".xlsx"));
//把xlxs輸出流作為輸入流輸入到zip輸出流中
zos.write(output.toByteArray());
zos.closeEntry();
output.close();
}
//關閉zos,但是outputStream流依然存在記憶體中
zos.close();
return genResponseEntityFromBytes(MediaType.APPLICATION_OCTET_STREAM,
downloadFileName, bos.toByteArray());