Jsf ApachePOI+;RichFaces 4-docx文件名

Jsf ApachePOI+;RichFaces 4-docx文件名,jsf,jakarta-ee,apache-poi,Jsf,Jakarta Ee,Apache Poi,我正在使用ApachePOI生成扩展名为.docx的文档。我在标头响应(HttpServletResponse)中设置了文件名,但浏览器在我的URL末尾保存了一个同名文件,例如: 我的浏览器中的URL是:localhost:8080/MyProject/mypage.jsf,下载文件的名称是mypage.jsf,忽略头中设置的名称(HttpServletResponse)。如果我编辑docx的文件扩展名,内容就可以了 代码如下: private void generateDocument

我正在使用ApachePOI生成扩展名为.docx的文档。我在标头响应(HttpServletResponse)中设置了文件名,但浏览器在我的URL末尾保存了一个同名文件,例如:

我的浏览器中的URL是:localhost:8080/MyProject/mypage.jsf,下载文件的名称是mypage.jsf,忽略头中设置的名称(HttpServletResponse)。如果我编辑docx的文件扩展名,内容就可以了

代码如下:

    private void generateDocument() throws IOException{
      XWPFDocument document = new XWPFDocument();
      //load document here

        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpServletResponse response = (HttpServletResponse) facesContext
                .getExternalContext().getResponse();

        response.reset();
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");

        ServletOutputStream out = response.getOutputStream();
        document.write(out);

        response.setHeader("Content-Disposition",
                "attachment; filename=my_document.docx");
        facesContext.responseComplete();            
}
另外,我用的是RichFaces4


感谢

将评论升级为回答:

在写入servlet输出流之前,应该将response.setHeader调用移动到。除非您的框架正在进行大量的缓冲,否则在您将excel文件写入流之前,框架就已经发送了响应头。头必须在数据之前发送,因此一旦开始发送数据,就不能再添加新的头

(大多数框架都有一点缓冲,因此在处理简单的文本输出时,即使在写了几行响应之后,也可以偷偷地插入一些额外的标题。如果可以避免的话,最好不要依赖它!)

您的代码应更改为:

    FacesContext facesContext = FacesContext.getCurrentInstance();
    HttpServletResponse response = (HttpServletResponse) facesContext
            .getExternalContext().getResponse();

    response.reset();
    response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
    response.setHeader("Content-Disposition",
            "attachment; filename=my_document.docx");

    ServletOutputStream out = response.getOutputStream();
    document.write(out);

    facesContext.responseComplete();          

在写入servlet输出流之前,是否尝试将response.setHeader调用移动到?我不知道您的servlet设置,但在大多数情况下,在编写内容之前都需要先处理所有的标题。另外,在设置响应完成之前,不要忘记刷新输出流并关闭它。@Gagravarr,它成功了!路易吉·门多萨,真的很有必要。谢谢大家。我们还必须考虑一下Luiggi Mendoza的评论。感谢您的解释。这取决于您的框架。大多数会自动冲洗关闭,但我想你可能会发现一个坏了,不。。。。