【问题标题】:Primefaces p:media PDF not loadingPrimefaces p:媒体PDF未加载
【发布时间】:2021-06-16 21:02:35
【问题描述】:

当我尝试加载包含 primefaces 媒体 pdf 的页面时,未加载 PDF。 我在我的 postconstruct 中生成 PDF,并将流媒体内容保存在单独的变量中。 在我的 JSF 中,我调用了 getStream 方法来返回流式内容。

JSF 页面:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
<ui:composition template="/templates/header.xhtml">
    <ui:define name="content">
        <f:metadata>
            <f:viewParam name="invoiceID" value="#{invoiceBean.invoiceID}"/>
        </f:metadata>
        <ui:param name="invoiceID" value="#{invoiceBean.invoiceID}"/>
        <h4 style="text-align: center;"><h:outputText
                value="#{msgs['invoice.thankYou']}"/></h4>
        <div class="card">
            <p:media value="#{invoiceBean.stream}" player="pdf" width="100%" height="800px">
                Your browser can't display pdf,
                <h:outputLink
                        value="#{invoiceBean.streamedContent}">click
                </h:outputLink>
                to download pdf instead.
            </p:media>
        </div>
    </ui:define>
</ui:composition>
</html>

豆子:

@Model
@Getter
@Setter
public class InvoiceBean {
    @Inject
    InvoiceService invoiceService;
    @Inject
    HttpServletRequest httpServletRequest;
    private Invoice invoice;
    private String invoiceID;
    private StreamedContent streamedContent;

    @PostConstruct
    public void initInvoice() {
        User user = getLoggedInUser();
        invoiceID = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("invoiceID");
        invoice = invoiceService.getInvoice(Long.parseLong(invoiceID));
        PDFGenerator pdf = new PDFGenerator(invoice);
        streamedContent = pdf.getStreamedContent();
    }

    public StreamedContent getStream() throws IOException{
        FacesContext context = FacesContext.getCurrentInstance();

        if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
            return new DefaultStreamedContent();
        } else {
            return streamedContent;
        }
    }
}

【问题讨论】:

  • 你可以只下载流媒体内容吗?
  • @JasperdeVries 它向我展示了一个像这样的空元素:&lt;object type="application/pdf" data="" height="800px" width="100%"&gt; Your browser can't display pdf, &lt;a href=""&gt;click &lt;/a&gt; to download pdf instead. &lt;/object&gt;
  • 我不会使用 p:media 我会使用 DocumentViewer 而不是它适用于所有浏览器:primefaces.org/showcase-ext/sections/documentviewer/basic.jsf
  • @Melloware streamedcontent 仍然为空我的 PDF 没有呈现它只是一直在旋转
  • 问题更多是生命周期问题,我认为它是在生成 PDF 之前渲染它

标签: primefaces


【解决方案1】:

因为流是动态的,来自@BalusC 的this post 对于解决这个问题非常有用。特别是“永远不要将 StreamedContent 或任何 InputStream 甚至 UploadedFile 声明为 bean 属性;只有当网络浏览器实际请求图像内容时,才在无状态 @ApplicationScoped bean 的 getter 中创建全新的。” /p>

p:media 标签需要禁用缓存。

                <p:media value="#{pdfViewController.pdf}" player="pdf" cache="false"
                    width="100%" height="500px" >
                    Your browser can't display pdf.
                </p:media>
                <br/>
                <h:form>
                    <p:commandButton value="Download" icon="pi pi-arrow-down" ajax="false">
                        <p:fileDownload value="#{pdfViewController.pdfDownload}" />
                    </p:commandButton>
                </h:form>

backing bean 需要在 getter 中完成所有工作,而不是在 PostConstruct 方法中。 (请参阅 @BalusC 的帖子中的 cmets。)我能够同时使用 Request(每个 Showcase)和 Session bean,但 PrimeFaces documentation 警告 ViewScoped。

@Named
@RequestScoped
public class PdfViewController implements java.io.Serializable {
    public StreamedContent getPdf() {
        return DefaultStreamedContent.builder()
                .contentType("application/pdf")
                .stream(() -> makePDFStream())
                .build();
    }

    protected ByteArrayInputStream makePDFStream() {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        String dt = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss-n"));
        makePDF(baos, "This message was created at " + dt);
        return new ByteArrayInputStream(baos.toByteArray());
    }

    // use iText to create a PDF document "on the fly"
    protected void makePDF(OutputStream os, String message) {
        PdfDocument pdf = new PdfDocument(new PdfWriter(os));
        try (Document document = new Document(pdf)) {
            String line = "Hello! Welcome to iTextPdf";
            document.add(new Paragraph(line));
            document.add(new LineSeparator((new SolidLine())));
            PdfFont font = PdfFontFactory.createFont(StandardFonts.TIMES_ITALIC);
            Text msgText = new Text(message).setFont(font).setFontSize(10);
            document.add(new Paragraph().add(msgText));
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, "PDF document creation error", ex);
        }
        // os is automatically written and closed when document is autoclosed
    }
}

为了支持下载选项,并且因为 bean 是 @request,所以会在需要时重新创建流。还需要包含.name("...)",而p:media value= 标记如果指定名称则失败,因此需要单独的方法。

    public StreamedContent getPdfDownload() {
        return DefaultStreamedContent.builder()
                .name("temp.pdf")
                .contentType("application/pdf")
                .stream(() -> makePDFStream())
                .build();
    }

使用 PrimeFaces v8 和 Wildfly v21 (w/Mojarra) 进行测试。

【讨论】:

    猜你喜欢
    • 2022-08-18
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    • 2015-07-02
    • 2015-10-31
    • 1970-01-01
    • 1970-01-01
    • 2014-06-22
    相关资源
    最近更新 更多