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

huangapple go评论115阅读模式
英文:

How can i zip multiple pdf files in Primefaces?

问题

我想将在数据表中选择的多个PDF文件压缩并让用户下载它们。

以下是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循环,我尝试生成包含所选列的PDF文档的zip文件。顺便说一下,我不确定我是否做得对。

使用“return(StreamedContent)output;”代码块,我尝试返回zip文件,但我得到“java.util.zip.ZipOutputStream无法强制转换为org.primefaces.model.StreamedContent”异常。我试图将ZipOutputStream转换为StreamedContent,因为使用了<p:fileDownload> Primefaces标签。

您能帮助我解决这个问题吗?

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(purchaseOrder.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 null; // 返回null以防止出现异常,您可以使用其他方式处理zip文件
            } catch (Exception ex) {
                System.out.println("生成时出错...");
                ex.printStackTrace();
            }
        }
    }

    return null;
}

请注意,您应该使用其他方式处理生成的zip文件,而不是尝试将ZipOutputStream转换为StreamedContent,因为它们是不同的类型。您可以将zip文件保存在服务器上,然后提供下载链接给用户。

英文:

I want to zip multiple pdf files which are selected in the data-table and let the user download them.

Here is XHTML;

&lt;p:commandLink id=&quot;print_orders&quot; 

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

&lt;/p:commandLink&gt;

Let me clarify managedbean side;

purchaseOrder object includes PO_NUMBER() I generate pdf document (pdfDoc) as ByteArrayOutputStream from SAP with PO_NUMBER(). With for loop I tried to produce zip file includes pdf documents as much as the selected column. By the way I'm not sure I did it right.

With "return (StreamedContent) output;" code block I tried to return zip file but I get "java.util.zip.ZipOutputStream cannot be cast to org.primefaces.model.StreamedContent" exception. I tried to convert ZipOutputStream to StreamedContent because of <p:fileDownload> Primefaces tag.

Can you help me with how to fix this problem?

 public StreamedContent printsAction()
{
    if(!termsAgreed)
        RequestContext.getCurrentInstance().execute(&quot;PF(&#39;warningDialog&#39;).show();&quot;);
    else
    {
        if (getSelectedPurchaseOrders() != null &amp;&amp; !getSelectedPurchaseOrders().isEmpty()) {
            
            try
            {
                FileOutputStream zipFile = new FileOutputStream(new File(&quot;PO_Reports.zip&quot;));
                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(&quot;error when generating...&quot;);
                    ex.printStackTrace();
            }
            
        }
    }
    
    return null;
}

答案1

得分: 4

You cannot simply cast a ZipOutputStream to StreamedContent as they don't have a parent-child relation. See link.

You should convert your InputStream (not the output stream) to streamed content. See for example link.

So, you need to do something like:

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

You cannot simply cast a ZipOutputStream to StreamedContent as they don't have a parent child relation. See https://stackoverflow.com/questions/45409944/how-can-i-cast-objects-that-dont-inherit-each-other.

You should convert your InputStream (not the output stream) to streamed content. See for example https://www.primefaces.org/showcase/ui/file/download.xhtml

So, you need to do something like:

DefaultStreamedContent.builder()
                .name(&quot;PO_Reports.zip&quot;)
                .contentType(&quot;application/zip&quot;)
                .stream(() -&gt; yourInputStream)
                .build();

答案2

得分: -1

I found solutions to these problems. Maybe this solution will help someone else. I would be grateful for any contribution on the new solution.

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;
}

这是您提供的代码的翻译部分。

英文:

I found solutions to these problems. Maybe this solution will help someone else. I would be grateful for any contribution on the new solution.

public StreamedContent printsAction() {
ByteArrayInputStream bis = null;
InputStream stream = null;
if (!termsAgreed) {
RequestContext.getCurrentInstance().execute(&quot;PF(&#39;warningDialog&#39;).show();&quot;);
} else {
if (getSelectedPurchaseOrders() != null &amp;&amp; !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, &quot;application/zip&quot;, &quot;PO_Reports.zip&quot;,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(&quot;PO_Report_&quot; + purchaseOrder.getPO_NUMBER() + &quot;.pdf&quot;);
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;
}

huangapple
  • 本文由 发表于 2020年7月28日 02:38:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/63121543.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定