Primefaces p:media PDF 未加载 [英] Primefaces p:media PDF not loading
问题描述
当我尝试加载包含 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屋!