我如何在 Primefaces 中压缩多个 pdf 文件?

How can i zip multiple pdf files in Primefaces?

我想压缩数据中选中的多个pdf文件-table让用户下载。

这是 XHTML;

<p:commandLink id="print_orders" 

        value="Print Selected Orders" ajax="false" 
        onclick="PrimeFaces.monitorDownload(startPrint, stopPrint);"  
        styleClass="button button--ujarak button--border-thin button--text-medium download"
        style="text-align: center;  float:none; margin: 0px auto 0px auto; padding: 0.05em 0.1em;" >
                            
        <p:fileDownload value="#{printOrdersManagedBeanSAP.printsAction()}" />

</p:commandLink>

让我澄清一下 managedbean 方面;

purchaseOrder 对象包括 PO_NUMBER() 我使用 PO_NUMBER() 从 SAP 生成 pdf 文档 (pdfDoc) 作为 ByteArrayOutputStream。使用 for 循环,我尝试生成 zip 文件,其中包括与所选列一样多的 pdf 文档。顺便说一句,我不确定我做对了。

使用“return (StreamedContent) 输出;”代码块 我尝试 return zip 文件,但出现“java.util.zip.ZipOutputStream 无法转换为 org.primefaces.model.StreamedContent”异常。由于 Primefaces 标记,我尝试将 ZipOutputStream 转换为 StreamedContent。

你能帮我解决这个问题吗?

 public StreamedContent printsAction()
{
    if(!termsAgreed)
        RequestContext.getCurrentInstance().execute("PF('warningDialog').show();");
    else
    {
        if (getSelectedPurchaseOrders() != null && !getSelectedPurchaseOrders().isEmpty()) {
            
            try
            {
                FileOutputStream zipFile = new FileOutputStream(new File("PO_Reports.zip"));
                ZipOutputStream output   = new ZipOutputStream(zipFile);
                
                for (PurchaseOrderSAP purchaseOrder : getSelectedPurchaseOrders()) {
                    
                    ByteArrayOutputStream pdfDoc = purchaseOrderSAPService.printOrder(selectedPurchaseOrder.getPO_NUMBER());
                    
                    ZipEntry zipEntry = new ZipEntry(purchaseOrder.getPO_NUMBER());
                    output.putNextEntry(zipEntry);
                    
                    InputStream targetStream = new ByteArrayInputStream(pdfDoc.toByteArray());
                    
                    IOUtils.copy(targetStream, output);
                    output.closeEntry();
                }
                
                output.finish();
                output.close();
                return (StreamedContent) output;
                
                
            }       
            catch(Exception ex)
            {
                    System.out.println("error when generating...");
                    ex.printStackTrace();
            }
            
        }
    }
    
    return null;
}

你不能简单地cast a ZipOutputStream to StreamedContent 因为他们没有父子关系。参见

您应该您的InputStream(不是输出流)转换为流媒体内容。例如参见 [​​=15=]

因此,您需要执行以下操作:

DefaultStreamedContent.builder()
                .name("PO_Reports.zip")
                .contentType("application/zip")
                .stream(() -> yourInputStream)
                .build();

我找到了解决这些问题的方法。也许这个解决方案会帮助别人。如果您对新解决方案做出任何贡献,我将不胜感激。

public StreamedContent printsAction() {
    ByteArrayInputStream bis = null;
    InputStream stream = null;
    if (!termsAgreed) {
        RequestContext.getCurrentInstance().execute("PF('warningDialog').show();");
    } else {
        if (getSelectedPurchaseOrders() != null && !getSelectedPurchaseOrders().isEmpty()) {
            try {
                if (zipBytes() != null) {
                    bis = new ByteArrayInputStream(zipBytes()); // Firstly I zip every PDF doc with zipBytes() method
                    stream = bis;
                    file = new DefaultStreamedContent(stream, "application/zip", "PO_Reports.zip",StandardCharsets.UTF_8.name());
                    return file;
                } else {
                    return null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (bis != null) {
                        bis.close();
                    }
                    if (stream != null) {
                        stream.close();
                    }
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        } else {
            return null;
        }
    }
    return null;
}

private byte[] zipBytes() {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ByteArrayOutputStream pdfDoc = new ByteArrayOutputStream();
    ZipOutputStream zos = new ZipOutputStream(baos);
    DataInputStream pdfDocIs = null;
    byte[] result = null;
    try {
        for(PurchaseOrderSAP purchaseOrder : getSelectedPurchaseOrders()) {
            pdfDoc = purchaseOrderSAPService.printOrder(purchaseOrder.getPO_NUMBER()); // PDF document comes from SAP as ByteArrayOutputStream
            pdfDocIs = new DataInputStream(new ByteArrayInputStream(pdfDoc.toByteArray()));
            ZipEntry zipEntry = new ZipEntry("PO_Report_" + purchaseOrder.getPO_NUMBER() + ".pdf");
            zos.putNextEntry(zipEntry);
            zos.write(toByteArray(pdfDocIs)); // Secondly in order to zip PDF doc i convert it to Byte Array with toByteArray method
        }
        zos.close();
        result =  baos.toByteArray();
    } catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        try {
            if (baos != null) {
                baos.close();
            }
            if (pdfDoc != null) {
                pdfDoc.close();
            }
            if (zos != null) {
                zos.close();
            }
            if (pdfDocIs != null) {
                pdfDocIs.close();
            }
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }
    return result;
}

public static byte[] toByteArray(InputStream in) {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    byte[] result = null;
    int len;
    // read bytes from the input stream and store them in buffer
    try {
        while ((len = in.read(buffer)) != -1) {
            // write bytes from the buffer into output stream
            os.write(buffer, 0, len);
        }
        result = os.toByteArray();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (os != null) {
                os.close();
            }
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }
    return result;
}