一尘不染

使用RichFaces下载文件

jsp

我已经完成以下工作:

  1. 用户可以上传文件(即压缩档案)
  2. 用户可以解压缩服务器上的文件
  3. 用户可以在这些文件上执行一些操作,从而生成更多文件

现在,我需要执行步骤4:

  • 用户可以再次将文件下载到自己的计算机上

谁能给我一个提示?我试图了解我在Google上发现的内容,但是它并没有达到预期的效果。我必须设置内容类型吗?当我设置应用程序/八位字节流时​​,只有txt和csv文件可以正确显示(在浏览器中,而不是我想要的下载弹出窗口),其他文件将无法工作…

JSP:

<a4j:commandLink value="Download" action="#{appController.downloadFile}" rendered="#{!file.directory}">
   <f:param name="file" value="#{file.absoluteFilename}" />
</a4j:commandLink>

appController:

public String downloadFile() {
    String filename = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("file");
    File file = new File(filename);
    HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();

    writeOutContent(response, file, file.getName());

    FacesContext.getCurrentInstance().responseComplete();
    return null;
}

private void writeOutContent(final HttpServletResponse res, final File content, final String theFilename) {
    if (content == null) {
        return;
    }
    try {
        res.setHeader("Pragma", "no-cache");
        res.setDateHeader("Expires", 0);
        res.setHeader("Content-disposition", "attachment; filename=" + theFilename);
        FileInputStream fis = new FileInputStream(content);
        ServletOutputStream os = res.getOutputStream();
        int bt = fis.read();
        while (bt != -1) {
            os.write(bt);
            bt = fis.read();
        }
        os.flush();
        fis.close();
        os.close();
    } catch (final IOException ex) {
        Logger.getLogger(ApplicationController.class.getName()).log(Level.SEVERE, null, ex);
    }
}

阅读 221

收藏
2020-06-08

共1个答案

一尘不染

您的具体问题是您尝试通过Ajax下载文件。这是不正确的。JavaScript无法处理二进制响应,也没有任何强制执行“ 另存为”
对话框的功能。您需要改为使其成为普通的同步请求,以便由Web浏览器本身来处理它。

<h:commandLink value="Download" action="#{appController.downloadFile}" rendered="#{!file.directory}">
   <f:param name="file" value="#{file.absoluteFilename}" />
</h:commandLink>

至于设置的内容类型,如果你有一个文件名以扩展在你的手中,你可以使用ServletContext#getMimeType()基于解决它<mime- mapping>web.xml(无论是服务器的默认的一个或你的web应用的一个)。

ServletContext servletContext = (ServletContext) externalContext.getContext();
String contentType = servletContext.getMimeType(file.getName());

if (contentType == null) {
    contentType = "application/octet-stream";
}

response.setContentType(contentType);
// ...

(请注意,我假设您正在使用JSF 1.x,看看如何获​​得servlet响应,因为JSF
2.x可以使用ExternalContext#getMimeType()

2020-06-08