【问题标题】:JSF PDF not downloadable while returned from Servlet [duplicate]从 Servlet 返回时无法下载 JSF PDF [重复]
【发布时间】:2020-04-22 02:44:39
【问题描述】:

我有一个表单,一旦完成就会打开一个新选项卡并调用我的 bean 方法 annonceReturn()。

此方法发回一个 pdf 文件。问题是当我用 _blank 打开一个新选项卡时,URL 以 .xhtml 结尾。甚至文件名也显示为在我的示例“list.xhtml”(URL 的最后一部分)中。问题是我无法下载此文件,因为它不被视为 pdf 文件。

这是我的 xhtml 文件:

<h:form id="form">    
    <p:commandButton id="envoiRetour" onclick="this.form.target = '_blank';"
        actionListener="#{returnCtrl.announceReturn()}" 
        value="Open PDF in new tab"
        ajax="false" />
</h:form>

这是 returnCtrl.annonceReturn() 方法:

public void announceReturn() throws MalformedURLException, FileNotFoundException, DocumentException, BadElementException, IOException, InterruptedException {
    String referenceAnnouncement = "C:/Users/path_to_my_pdf_file.pdf";
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
    BufferedInputStream input = null;
    BufferedOutputStream output = null;

    try {
        input = new BufferedInputStream(new FileInputStream(referenceAnnouncement), 10240);
        response.reset();
        response.setHeader("Content-type", "application/pdf"); 
        response.setContentLength((int)new File(referenceAnnouncement).length());
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setHeader("Content-disposition", "inline; filename=" + "file.pdf");
        response.setHeader("pragma", "public");

        output = new BufferedOutputStream(response.getOutputStream(), 10240);
        byte[] buffer = new byte[10240];
        int length;
        while ((length = input.read(buffer)) > 0) {
            output.write(buffer, 0, length);
        }
        output.flush();
    } finally {
        output.close();
        input.close();
    }
}

如何在新标签页中打开此 PDF 并能够下载?

当我尝试下载它时,它说存在网络错误(并尝试将其保存为 xhtml 文件)。

编辑:这是帮助我的问题:How to open a PDF file in a new tab

EDIT 2:问题不在于 PDF 不显示。问题是它显示在新选项卡中,但是当我尝试下载它时,资源管理器希望将其保存为 XHTML 文件。

EDIT 3 : 如此处提到的 -> Open PDF in new tab, saving file gives wrong file name 如果处置不是“附件”,似乎文件名被忽略......所以我想我需要考虑另一种方法来做到这一点。

感谢您的宝贵时间。

【问题讨论】:

  • servlet 在哪里? (然后是使用的 jsf servlet)以及您尝试了 stackoverflow 中的许多 Q/A 中的哪一个,为什么它们没有帮助。您是否调查过“服务器错误”?
  • 试过p:fileDownload (link)?
  • 你想让我编辑我的帖子以链接网站的所有链接,解释如何在我读过的新标签中下载或打开 pdf 吗?
  • 使用 Servlet 而不是 JSF 支持 bean 可以解决您的问题。具有讽刺意味的是,您在问题的当前标题中提到您使用的是 Servlet,但实际上您使用的是 JSF 支持 bean ..
  • 没有。这是有问题的客户端。在 Chrome 等普通浏览器中一切正常。这与使用的服务器端框架无关。在使用 PHP、C、Python 或其他任何东西而不是 Java 时,您会遇到完全相同的问题。

标签: pdf internet-explorer jsf download


【解决方案1】:

我已经在我的项目中测试过,这里是解决方案:

1 - 创建按钮

<h:commandButton
    onclick="this.form.target='_blank'"
    id="cmdOpenPDF"
    action="#{bean.openPDF(bean.code)}"
    value="New PDF">
</h:commandButton>

2 - bean 有一个带有指向 PDF 的重定向链接的函数。此示例是根文件夹中的 pdf。

  public void openPDF(String code) throws Exception {
  String filePdfName ="";
  try {

     //Make sure that this file in root

     File pdf = new File("sample.pdf"); 

     filePdfName = pdf.getName();

     } catch (Exception ex) {
        ex.printStackTrace();
     }
     ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
     ec.redirect(ec.getRequestContextPath() + "/" + filePdfName);
}

【讨论】:

  • 这个问题是当用户单击“提交”时,我在支持 bean 中创建了 PDF 文件。我无法将其保存在根文件夹中,因为每次我将项目推送到 prod 时,我都会删除所有这些文件。
  • 我认为你可以在生产环境中创建一个像 '$web-root/temp/' 这样的文件夹。然后修改代码 ec.redirect(ec.getRequestContextPath() + "/temp/" + filePdfName);
  • @VinhCanCode:永远不要在你的 web 应用中存储文件。防止这种情况的非常简单的解决方案已经存在了 20 多年。副本包含所有信息......一个servlet......可以从文件系统中的任何位置读取
【解决方案2】:

这是我的代码,希望对你有帮助。

FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();

File temp = File("./path/abc.pdf");
temp.deleteOnExit();
ec.responseReset(); 
ec.setResponseContentType("application/pdf"); 
ec.setResponseContentLength((int)temp.length()); 
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + temp.getName() + "\""); //inline; 

OutputStream output = ec.getResponseOutputStream();

Files.copy(temp.toPath(), output);
fc.responseComplete();

【讨论】:

  • 感谢您的回复。但是,当您将 Content-Disposition 设置为“附件”时,文件会立即下载,对吗?
  • 是的。我还设置了文件大小。
  • 我不想下载 pdf,我希望它在新标签页中打开,但如果用户愿意,可以让其下载。
  • 你能把我的代码改成“Content-Disposition”、“inline;”...吗?希望它有效。
  • 我试过了,但 PDF 仍然在浏览器中正确显示。当我尝试下载它时,它会尝试将其另存为 XHTML 文件,但它失败了
【解决方案3】:

尝试使用“附件”而不是“内联”来强制浏览器保存文件(而不是尝试使用相关插件打开 - 如果已安装)

 response.setHeader("Content-disposition", "attachment; filename=" + "file.pdf");

希望对你有帮助。

贝佩

【讨论】:

  • 感谢您的回复。由于 Content-Disposition 是“附件”,文件会立即下载,对吗?我不希望下载 pdf,我希望它在新选项卡中打开,但如果用户愿意,请让其下载。
  • 我明白了,尝试完全删除'Content-Disposition'并让浏览器处理它,如果启用了插件,它应该打开PDF。
  • 我试过了,但没有任何改变。文件名似乎设置不正确。
  • 它是否适用于您从网上下载的其他 PDF?只是为了确保浏览器正确启用了插件
  • 我的网站上有一个链接可以重定向到 pdf,它可以正常工作,因为 URL 以“pdf”结尾。在这种情况下,URL 以“.xhtml”结尾,它似乎覆盖了我在 Content-Disposition 中传递的文件名。
猜你喜欢
  • 2019-06-21
  • 1970-01-01
  • 2019-01-24
  • 1970-01-01
  • 2016-02-21
  • 2017-06-08
  • 1970-01-01
  • 2011-04-04
  • 1970-01-01
相关资源
最近更新 更多