JSF2.0:加载时显示某个pdf页面

时间:2017-09-12 10:50:14

标签: pdf jsf

我想在JSF2的新页面中打开PDF,并在加载时在此pdf中显示某个页面。我的jsf页面中有一种TOC,想直接从那里跳到PDF中的页面。

我所知道的(这不是,我需要的,只是给adobe reader和其他pdf阅读器提供我要跳转到的页面的一个例子): 这样的东西会打开页面(从互联网上选择一些东西): https://www.cdc.gov/diabetes/pdfs/data/statistics/national-diabetes-statistics-report.pdf#page=10

#page = 10使浏览器显示页面10的pdf插件。

选择PDF的要求:

  • PDF是根据必须只驻留在ManagedBeans中的ID从webservice动态下载的,因为它是秘密的,不应该传递给其他人(如会话ID ...)(下面给出的是anser by我传递GET参数中的ID,这不应该这样做)
  • PDF不应该驻留在文件系统中,因为我不想处理临时文件(以下给出的答案实际上是在FS上使用PDF,只有流不起作用)

现在我真正的问题:我必须更改在JSF中显示/使用的URL,但不能使用和includeViewParams一样的正常方式,因为这将插入"?",而不是"#"在网址中。

另外,我有一个支持bean,它根据我给出的其他一些参数从后端服务获取PDF的内容,所以解决方案很酷,但我知道这可能是不可能的......

有没有人有想法,如何解决这个问题? 我没有包含任何代码,因为它无论如何都不起作用,而且我可能需要一种全新的方法来解决这个问题......

2 个答案:

答案 0 :(得分:0)

事实证明,Primefaces已经实现了这一点(虽然实现有它的限制):

<p:media player="pdf" value="#{viewerBean.media}" width="100%" height="100%">
    <f:param name="#page" value="#{viewerBean.pageNumber}"/>
    <f:param name="toolbar" value="1"/>
    <!--<f:param name="search" value="#{viewerBean.queryText}"/>-->
</p:media>

https://www.primefaces.org/showcase/ui/multimedia/media.xhtml

限制:无法从流中读取,至少不是很稳定。节省能源,并将流写入临时文件,并动态设置此文件名。不确定,这是否完整,但你应该明白:

import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import java.io.*;
import javax.annotation.PostConstruct;
import java.nio.file.Files;
import java.nio.file.Paths;

@ManagedBean
@RequestScoped
public class ViewerBean implements Serializable {
  @ManagedProperty(value = "#{param.page}")
  private String pageNumber;

  private File media;

    @PostConstruct
  public void init() {
    try {
      media = Files.createTempFile("car", ".pdf").toFile();
      try (FileOutputStream outputStream = new FileOutputStream(media)) {
        IOUtils.copy(getStreamedContent().getStream(), outputStream);
      }
    } catch (IOException e) {
      LOGGER.error(e);
      throw new RuntimeException("Error creating temp file", e);
    }
  }
  public StreamedContent getMedia() {
    try {
      return new DefaultStreamedContent(new FileInputStream(media), "application/pdf");
    } catch (FileNotFoundException e) {
      String message = "Error reading file " + media.getAbsolutePath();
      LOGGER.error(message, e);
      throw new RuntimeException(message, e);
    }
  }
}

如果不需要页面名称,您可以使用: http://balusc.omnifaces.org/2006/05/pdf-handling.html

也许如果你可以使用outputLink,你会很幸运,但我没时间测试这个选项。

答案 1 :(得分:0)

找到(THE)解决方案;以上回答提及,但这不能处理@ViewScope bean,并向底层bean发送许多请求,只读取一个InputStream。我发现由于负载原因这是不可接受的。

所以我们走了:

  1. 使用<f:event type="preRenderView" listener="#{documentDownloadBean.writeIntpuStreamToResponseOutputStream}"/>
  2. 创建JSF页面
  3. 将动态检索PDF的必要数据放入闪存范围
  4. 重定向到上面的JSF页面,如:return "document_search/view_pdf.xhtml?faces-redirect=true#page=" + page;

    @ManagedBean
    @ViewScoped
    public class DocumentDownloadBean implements Serializable {
    
      @ManagedProperty(value = "#{documentSearchBean}")
      private DocumentSearchBean documentSearchBean;
    
      public String activeDocumentToFlashScope(String page) {
        Document document = documentSearchBean.getSelectedDocument();
        FacesContext.getCurrentInstance().getExternalContext().getFlash().put("document", document);
        // everything preapared now, redirect to viewing JSF page, with page=xxx parameter in URL, which will be evaluated by adobe pdf reader (and other readers, too)
        return "document_search/view_pdf.xhtml?faces-redirect=true#page=" + page;
      }
    
      public void download() {
        Document document = (Document) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("document");
        InputStream inputStream = getInputstreamFromBackingWebserviceSomehow(document);
        FacesUtils.writeToResponseStream(FacesContext.getCurrentInstance().getExternalContext(), inputStream, document.getFileName());
      }
    
    }
    
  5. 调用JSF页面:

            <p:commandLink id="outputText" action="#{documentDownloadBean.activeDocumentToFlashScope(selectedDocument, page)}"
                           target="_blank" ajax="false">
              <h:outputText value="View PDF"/>
            </p:commandLink>