链接在JSF下载zip文件

时间:2015-01-06 09:18:41

标签: jsf primefaces download

我在服务器中有一个zip文件。我想点击链接下载该文件。

有没有办法在JSF或PrimeFaces中创建一个下载zip文件的链接,比如客户端下面的HTML5 download属性?

<a href="/images/myw3schoolsimage.jpg" download>

2 个答案:

答案 0 :(得分:8)

HTML5 download属性与它无关。它只允许您指定应出现在另存为对话框中的备用文件名。

E.g。

<a href="foo.zip" download="bar.zip" />

将显示另存为对话框,其中bar.zip为文件名,但实际上提供的内容为foo.zip。请注意,bar.zip并不一定需要存在于服务器中。


关于您的具体问题,有几种方法可以在JSF Web应用程序中提供文件下载。

  1. 只需将该文件放入公共网页内容文件夹即可。

    WebContent
     |-- META-INF
     |-- WEB-INF
     |-- files
     |    `-- foo.zip
     |-- page.xhtml
     :
    

    然后您可以将其称为:

    <a href="#{request.contextPath}/files/foo.zip">download foo.zip</a>
    
  2. 或者,如果它是外部文件夹而您无法将其移动到公共网页内容中,那么只需告诉服务器发布它即可。例如。当您在/path/to/files路径中拥有所有这些文件并且您正在使用Tomcat服务器时,请将以下内容添加到Tomcat <Host>的{​​{1}}元素中:

    /conf/server.xml

    然后您可以将其称为:

    <Context docBase="/path/to/files" path="/files" />
    
  3. 或者,如果您无法以某种方式控制服务器配置,或者无法确定将任意文件夹作为新的Web上下文发布的特定于服务器的方式,或者它代表一个临时存储文件夹,您可以#39;而不是发布到Web上,然后创建一个完成工作的Web servlet。将缓存和恢复留在外面考虑,它很简单:

    <a href="/files/foo.zip">download foo.zip</a>
    

    您可以像#1一样引用它:

    @WebServlet("/files/*")
    public class FileServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String filename = request.getPathInfo().substring(1);
            File file = new File("/path/to/files", filename);
            response.setHeader("Content-Type", getServletContext().getMimetype(filename));
            response.setHeader("Content-Length", String.valueOf(file.length()));
            response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
            Files.copy(file.toPath(), response.getOutputStream());
        }
    
    }
    

答案 1 :(得分:3)

虽然这是一个老问题,但我想将此添加到@BalusC的完整答案(由于声誉低而没有评论):@BalusC的第三个解决方案(使用@WebServlet)如果按原样复制粘贴,则会导致“路径遍历攻击”。

您可以使用URL尝试攻击(对于Linux服务器):

<yourApplicationURLUntilContextPath>/files/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/etc/passwd

这个问题有各种解决方案。一个是,在将文件复制到输出流之前添加以下检查:

if(!file.getAbsolutePath().equals(file.getCanonicalPath()))
{
response.sendError(404);
}

您可以参考link获取路径遍历攻击的更多解决方案。

希望它能帮助一些开发人员......