Primefaces p:media PDF 未加载 [英] Primefaces p:media PDF not loading

查看:91
本文介绍了Primefaces p:media PDF 未加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

JSF 页面:

</f:元数据><ui:param name="invoiceID";值=#{invoiceBean.invoiceID}"/><h4 style="text-align: center;"><h:outputTextvalue="#{msgs['invoice.thankYou']}"/></h4><div class="card"><p:media value="#{invoiceBean.stream}";播放器=pdf"宽度=100%"高度=800像素">您的浏览器无法显示 pdf,<h:输出链接值=#{invoiceBean.streamedContent}">点击</h:outputLink>改为下载pdf.</p:media>

</ui:define></ui:composition></html>

豆子:

@Model@Getter@Setter公共类 InvoiceBean {@注入发票服务发票服务;@注入HttpServletRequest httpServletRequest;私人发票发票;私人字符串发票ID;私有流内容流内容;@PostConstruct公共无效initInvoice(){用户用户 = getLoggedInUser();invoiceID = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(invoiceID");invoice = invoiceService.getInvoice(Long.parseLong(invoiceID));PDFGenerator pdf = new PDFGenerator(发票);流内容 = pdf.getStreamedContent();}public StreamedContent getStream() 抛出 IOException{FacesContext 上下文 = FacesContext.getCurrentInstance();if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {返回新的 DefaultStreamedContent();} 别的 {返回流内容;}}}

解决方案

因为流是动态的,这篇文章 对解决这个问题非常有用.特别是永远不要将 StreamedContent 或任何 InputStream 甚至 UploadedFile 声明为 bean 属性;只有当 webbrowser 实际请求图像内容时,才在无状态 @ApplicationScoped bean 的 getter 中创建它."

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

 <p:fileDownload value="#{pdfViewController.pdfDownload}";/></p:commandButton></h:form>

支持 bean 需要在 getter 中完成所有工作,而不是在 PostConstruct 方法中.(请参阅@BalusC 帖子中关于此的评论.)我能够同时使用请求(每个展示)和会话 bean,但是 PrimeFaces 文档 警告不要使用 ViewScoped.

@Named@RequestScoped公共类 PdfViewController 实现 java.io.Serializable {公共流内容 getPdf() {返回 DefaultStreamedContent.builder().contentType(应用程序/pdf").stream(() -> makePDFStream()).建造();}受保护的 ByteArrayInputStream makePDFStream() {ByteArrayOutputStream baos = new ByteArrayOutputStream();String dt = LocalDateTime.now().format(DateTimeFormatter.ofPattern(yyyyMMdd-HHmmss-n"));makePDF(baos, "此消息是在 " + dt 上创建的);返回新的 ByteArrayInputStream(baos.toByteArray());}//使用 iText即时"创建 PDF 文档;protected void makePDF(OutputStream os, String message) {PdfDocument pdf = new PdfDocument(new PdfWriter(os));尝试(文档文档=新文档(pdf)){字符串行 = "你好!欢迎使用 iTextPdf";document.add(new Paragraph(line));document.add(new LineSeparator((new SolidLine())));PdfFont 字体 = 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 文档创建错误", ex);}//当文档被自动关闭时,os 被自动写入和关闭}}

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

 public StreamedContent getPdfDownload() {返回 DefaultStreamedContent.builder().name(temp.pdf").contentType(应用程序/pdf").stream(() -> makePDFStream()).建造();}

使用 PrimeFaces v8 和 Wildfly v21(带 Mojarra)进行测试.

When I try to load my page including a primefaces media pdf the PDF is not loaded. I generate the PDF in my postconstruct and keep the streamedcontent in a seperate variable. In my JSF I call the getStream method that returns the streamedcontent.

JSF page:

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

Bean:

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

解决方案

Because the stream is dynamic, this post from @BalusC is very useful to resolve this issue. In particular "never declare StreamedContent nor any InputStream or even UploadedFile as a bean property; only create it brand-new in the getter of a stateless @ApplicationScoped bean when the webbrowser actually requests the image content."

The p:media tag needs to disable the cache.

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

The backing bean needs to do all the work in the getter, not in the PostConstruct method. (See the comments in @BalusC's post about this.) I was able to use both Request (per Showcase) and Session beans, but the PrimeFaces documentation warns against 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
    }
}

In order to support the download option and because the bean is @request, the stream is recreated when needed. It was also necessary to include the .name("...)", whereas the p:media value= tag failed if name is specified, hence it needs a separate method.

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

Tested with PrimeFaces v8 and Wildfly v21 (w/Mojarra).

这篇关于Primefaces p:media PDF 未加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆