使用 Java、Struts 2 和 AJAX 下载文件

Posted

技术标签:

【中文标题】使用 Java、Struts 2 和 AJAX 下载文件【英文标题】:File download using Java, Struts 2 and AJAX 【发布时间】:2011-01-08 12:18:27 【问题描述】:

我想使用 java、struts2 和 ajax 提供文件下载。

在我的 html 页面上有一个名为“export”的按钮,点击哪个 ajax 调用将执行查询并使用代码创建 .xls 文件,我想将该文件提供给用户下载而不存储它在硬盘上。

有人知道如何在java中使用struts2和ajax吗?

有例子吗?

如果您需要我提供更多详细信息,请告诉我...

谢谢。

amar4kintu

【问题讨论】:

【参考方案1】:

在这种情况下,您不必使用 AJAX。只需让您的按钮将表单提交给您的 Struts 操作,并让该操作使用 stream result 类型。

例子:

在您的 Struts XML 中:

<result name="download" type="stream">
    <param name="contentDisposition">attachment;filename=report.xls</param>
    <param name="contentType">application/vnd.ms-excel</param>
    <param name="inputName">inputStream</param>
    <param name="bufferSize">1024</param>
</result>

然后您的操作将提供一个public InputStream getInputStream() 来传递数据。

我认为您用来生成 Excel 文件的任何库 (POI?) 都可以将输出写入任意的OutputStream

一种将其转换为InputStream 的快捷方式:

// Using Workbook from Apache POI for example...
Workbook wb;
// ...
ByteArrayOutputStream bos = new ByteArrayOutputStream();
wb.write(bos);
InputStream bis = new ByteArrayInputStream(bos.toByteArray());

【讨论】:

您好,我在我的 struts.xml 中添加了以下内容 application/vnd.ms-excel fileStream attachment;filename=report.xls 1024 现在我按照您的说明进行操作,但它提供的文件下载操作名称为 ExportReport.action 而不是 report.xls 所以应该是什么原因? 那么,您使用的是 MSIE?将文件名作为 URL 路径信息传递,或者使用更好的网络浏览器。 我使用的是 firefox,它应该给我下载文件为 report.xls,但它给了我 ExportReport.action 下载。如果我将其重命名为report.xls。它显示了我正在导出的完美 .xls 文件。谁能告诉我我错过了什么?【参考方案2】:

仅供参考,我们可以使用 Annotation 来做同样的事情:

public class MyAction 
    private InputStream fileInputStream;
    private String logoName;

    @Action(value="/downloadLogo", 
        results=
            @Result(name="success", type="stream", 
            params = 
                    "contentType", "application/image/gif",
                    "inputName", "fileInputStream",
                    "contentDisposition", "filename=\"$logoName\"",
                    "bufferSize", "1024"
            )
                   
    )    
    public String downloadLogo() throws Exception 
        logoName = "test.jpg";
            fileInputStream = new FileInputStream(new File("DirePath", logoName));
    

【讨论】:

【参考方案3】:

作为 amar4kintu 关于保存为 ExportReport.action 而不是 report.xls 文件的问题的后续行动,如果您的 struts.xml 文件中未遵循以下格式,则会在 IE 中发生这种情况:

<result name="download" type="stream">
        <param name="contentDisposition">attachment;filename="$flashcardSetBean.title.xlsx"</param>
        <param name="contentType">application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</param>
        <param name="inputName">inputStream</param>
        <param name="bufferSize">1024</param>
</result>

似乎contentDisposition 行特别必须表明该文件是一个附件并且文件名用引号括起来。

【讨论】:

【参考方案4】:

我会在 Action 类上使用这种注释:

@Result(name = "success", type= StreamResult.class,
          params = "contentType", "application/vnd.ms-excel",
                    "contentDisposition", "attachment; filename=report.xls",
          value = "reportFileStream"
)

【讨论】:

【参考方案5】:

下面解释了一种将输出流传输到输入流的更好方法 as opposed to the response by ZoogieZork above

InputStream is = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream((PipedInputStream) is);
wb.write(out);

这种方法的优点是整个缓冲区不存储在内存中,而是使用一个小的内部循环缓冲区进行管道传输。这在内存和 CPU 开销方面都更好。

参考: Convert a Java OutputStream to an InputStream

【讨论】:

【参考方案6】:

atlast,我能够解决它如下.. 我在我的动作类函数中写了以下行,我能够下载名称为 report.xls 而不是 ExportReport.action 的文件。我不知道确切..为什么?

response.setHeader("Content-Disposition","attachment;filename=rpt.xls"); 

以下内容在我的struts.xml 文件中。我从中删除了&lt;contentDispositin&gt; 参数,因为它不能从struts.xml 文件中工作,我将它放在我的操作Java 文件中,如上所述。

<result name="success"  type="stream" >
    <param name="inputName">fileStream</param>
    <param name="contentType">application/vnd.ms-excel</param>
    <param name="bufferSize">1024</param>
</result>

希望这会对某人有所帮助。

谢谢。

amar4kintu

【讨论】:

以上是关于使用 Java、Struts 2 和 AJAX 下载文件的主要内容,如果未能解决你的问题,请参考以下文章

struts2发送ajax的几个问题(不使用struts2-json-plugin的情况下)

Java基础101 Struts2下的 jquery+ajax+struts 技术实现异步刷新功能

struts2-ajax-jQuery

Struts 2 Ajax url 和 div 标签不适用于 struts 文件标签

Struts 2常用的Ajax标签

Struts2:Json插件_Ajax