【问题标题】:JSF2.0: Show certain pdf page on loadJSF2.0:加载时显示某些 pdf 页面
【发布时间】:2017-09-22 16:13:54
【问题描述】:

我想在 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 使浏览器的pdf插件显示第10页。

选择 PDF 的要求:

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

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

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

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

【问题讨论】:

  • 通过 servlet 提供 pdf 服务...简单明了。没有任何 jsf 有效相关(查看您所需的 url)
  • 我稍微澄清了这个问题,Servlet 可能不是一个选项,因为我无法访问打开 PDF 流所需的秘密

标签: pdf jsf


【解决方案1】:

事实证明,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,也许您会很幸运,但我没时间测试这个选项。

【讨论】:

  • 您能否解释一下 Stackoverflow 中所有类似的问答在哪里/为什么对您失败以及您(认为您)需要先将其写入文件?以我的拙见,这是针对您没有找到解决方案的不同问题的解决方法.... 干杯
  • 未提及,如何跳转到pdf中的特定页面。
【解决方案2】:

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

所以我们开始:

  1. &lt;f:event type="preRenderView" listener="#{documentDownloadBean.writeIntpuStreamToResponseOutputStream}"/&gt;创建JSF页面
  2. 将动态检索 PDF 所需的数据放入 Flash 范围内
  3. 像这样重定向到上面的 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());
      }
    
    }
    

调用 JSF 页面:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-10
    • 1970-01-01
    • 2013-11-17
    • 1970-01-01
    • 2020-08-31
    • 2018-02-23
    • 1970-01-01
    • 2018-02-02
    相关资源
    最近更新 更多