如何将两个 jasperReports 放在一个 zip 文件中进行下载?

How to put two jasperReports in one zip file to download?

public String generateReport()    {
 try

            {

                final FacesContext facesContext = FacesContext.getCurrentInstance();
                final HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
                response.reset();
                response.setHeader("Content-Disposition", "attachment; filename=\"" + "myReport.zip\";");
                final BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
                final ZipOutputStream zos = new ZipOutputStream(bos);

                for (final PeriodScale periodScale : Scale.getPeriodScales(this.startDate, this.endDate))
                {
                    final JasperPrint jasperPrint = JasperFillManager.fillReport(
                        this.reportsPath() + File.separator + "periodicScale.jasper",
                        this.parameters(this.reportsPath(), periodScale.getScale(),
                            periodScale.getStartDate(), periodScale.getEndDate()),
                        new JREmptyDataSource());

                    final byte[] bytes = JasperExportManager.exportReportToPdf(jasperPrint);
                    response.setContentLength(bytes.length);

                    final ZipEntry ze = new ZipEntry("periodicScale"+ periodScale.getStartDate() + ".pdf"); // periodicScale13032015.pdf for example
                    zos.putNextEntry(ze);
                    zos.write(bytes, 0, bytes.length);
                    zos.closeEntry();
                }
                zos.close();
                facesContext.responseComplete();
            }
            catch (final Exception e)
            {
                e.printStackTrace();
            }

            return "";
}

这是我在 managedBean 中的操作方法,用户调用它来打印 JasperReport,但是当我尝试将多个报告放入 zip 文件时它不起作用。

getPeriodScales 正在返回两个对象并且 JasperFillManager.fillReport 是 运行 正确的报告打印当我只是为一份报告生成数据时,当我尝试流式传输两个报告并在 WinRar 中只打开一个出现并且我得到一个 "unexpedted end of archive",在 7zip 中都出现但第二个已损坏。

我哪里做错了,或者有没有办法在不压缩的情况下流式传输多个报告?

我想通了,我将响应的 contentLenght 设置为 bytes.length 大小,但它应该是 bytes.length * Scale.getPeriodScales(this.startDate, this.endDate).size()

public JasperPrint generatePdf(long consumerNo) {
    Consumer consumerByCustomerNo = consumerService.getConsumerByCustomerNo(consumerNo);
    consumerList.add(consumerByCustomerNo);

    BillHeaderIPOP billHeaderByConsumerNo = billHeaderService.getBillHeaderByConsumerNo(consumerNo);
    Long billNo = billHeaderByConsumerNo.getBillNo();

    List<BillLineItem> billLineItemByBilNo = billLineItemService.getBillLineItemByBilNo(billNo);

    System.out.println(billLineItemByBilNo);
    List<BillReadingLine> billReadingLineByBillNo = billReadingLineService.getBillReadingLineByBillNo(billNo);


    File jrxmlFile = ResourceUtils.getFile("classpath:demo.jrxml");
    JasperReport jasperReport = JasperCompileManager.compileReport(jrxmlFile.getAbsolutePath());


    pdfContainer.setName(consumerByCustomerNo.getName());
    pdfContainer.setTelephone(consumerByCustomerNo.getTelephone());
    pdfContainer.setFromDate(billLineItemByBilNo.get(0).getStartDate());
    pdfContainer.setToDate(billLineItemByBilNo.get(0).getEndDate());
    pdfContainer.setSupplyAddress(consumerByCustomerNo.getSupplyAddress());
    pdfContainer.setMeterNo(billReadingLineByBillNo.get(0).getMeterNo());
    pdfContainer.setBillType(billHeaderByConsumerNo.getBillType());
    pdfContainer.setReadingType(billReadingLineByBillNo.get(0).getReadingType());
    pdfContainer.setLastBilledReadingInKWH(billReadingLineByBillNo.stream().filter(billReadingLine -> billReadingLine.getRegister().contains("KWH")).collect(Collectors.toList()).get(0).getLastBilledReading());
    pdfContainer.setLastBilledReadingInKW(billReadingLineByBillNo.stream().filter(billReadingLine -> billReadingLine.getRegister().contains("KW")).collect(Collectors.toList()).get(0).getLastBilledReading());
    pdfContainer.setReadingType(billReadingLineByBillNo.get(0).getReadingType());
    pdfContainer.setRateCategory(billLineItemByBilNo.get(0).getRateCategory());

    List<PdfContainer> pdfContainerList = new ArrayList<>();
    pdfContainerList.add(pdfContainer);

    Map<String, Object> parameters = new HashMap<>();
    parameters.put("billLineItemByBilNo", billLineItemByBilNo);
    parameters.put("billReadingLineByBillNo", billReadingLineByBillNo);
    parameters.put("consumerList", consumerList);
    parameters.put("pdfContainerList", pdfContainerList);

    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
    return jasperPrint;
}

//above code is accroding to my requirement , you just focus on the jasperPrint object which am returning , then jasperPrint object is being used for pdf generation , storing those pdf into a zip file .

@GetMapping("/batchpdf/{rangeFrom}/{rangeTo}")
    public String batchPdfBill(@PathVariable("rangeFrom") long rangeFrom, @PathVariable("rangeTo") long rangeTo) throws JRException, IOException {
        consumerNosInRange = consumerService.consumerNoByRange(rangeFrom, rangeTo);

        String zipFilePath = "C:\Users\Barada\Downloads";
        FileOutputStream fos = new FileOutputStream(zipFilePath +"\"+ rangeFrom +"-To-"+ rangeTo +"--"+ Math.random() + ".zip");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        ZipOutputStream outputStream = new ZipOutputStream(bos);
        try {
            for (long consumerNo : consumerNosInRange) {
                JasperPrint jasperPrint = generatePdf(consumerNo);
                byte[] bytes = JasperExportManager.exportReportToPdf(jasperPrint);
                outputStream.putNextEntry(new ZipEntry(consumerNo + ".pdf"));
                outputStream.write(bytes, 0, bytes.length);
                outputStream.closeEntry();
            }
        } finally {
            outputStream.close();
        }
        return "All Bills PDF Generated.. Extract ZIP file get all Bills";
    }
}