使用JSF下载CSV文件

5
我不知道如何下载CSV文件。 CSV将在运行时生成。我需要首先将文件保存在tomcat WEB-INF目录中吗? 我正在使用JSF 1.2。
顺便问一下,这种任务的首选JSF组件是什么?

编辑 (05.05.2012 - 15:53)

我尝试了BalusC在他的第一个链接中提到的解决方案,但是如果我点击我的commandButton,则文件的内容会显示在网页上。也许mimetype有问题?

xhtml文件:

<a4j:form>
    <a4j:commandButton action="#{surveyEvaluationBean.doDataExport}" value="#{msg.srvExportButton}" />
</a4j:form>

主要bean:
    public String doDataExport() {

    try {
        export.downloadFile();  
    } catch (SurveyException e) {
        hasErrors = true;
    }
    return "";
}

导出-bean:

public void downloadFile() throws SurveyException {

    try {

        String filename = "analysis.csv";

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

        response.reset();
        response.setContentType("text/comma-separated-values");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");

        OutputStream output = response.getOutputStream();

        // writing just sample data
        List<String> strings = new ArrayList<String>();

        strings.add("filename" + ";" + "description" + "\n");
        strings.add(filename + ";" + "this is just a test" + "\n");

        for (String s : strings) {
            output.write(s.getBytes());
        }

        output.flush();
        output.close();

        fc.responseComplete();

    } catch (IOException e) {
        throw new SurveyException("an error occurred");
    }
}

编辑 (05.05.2012 - 16:27)

我解决了我的问题。我必须使用 <h:commandButton> 而不是 <a4j:commandButton>,现在它可以运行了!

2个回答

4

我需要先把文件保存在Tomcat WEB-INF目录中吗?

不需要,只需将其直接写入HTTP响应正文,使用ExternalContext#getResponseOutputStream()获取相应的输出流,并设置适当的响应头,告诉浏览器它将要检索什么内容。

根据以下答案中的具体示例进行计算:

基本上:

List<List<Object>> csv = createItSomehow();
writeCsv(csv, ';', ec.getResponseOutputStream());

顺便问一下,这种任务中最喜欢的jsf组件是什么?

这是主观的。但无论如何,我们正在使用<p:dataExporter>并非常满意。


我认为我不能使用PrimeFaces,因为他们从PrimeFaces 2.0开始就不支持JSF 1.2了,这是对的吗? - yves.beutler
1
没错,古老的JSF 1.x即将面临生命周期的结束,因此您不应该期望有新的组件库支持它。只需手动流式传输即可。您只需要通过ExternalContext#getResponse()获取原始的HttpServletResponse,然后调用其getOutputStream()方法即可,但这已经在第一个链接中概述了。或者,当然,升级到JSF 2。它比JSF 1.2提供了许多优势。 - BalusC
我知道JSF 1.2的缺点,但目前我们无法升级到更高的版本。我尝试理解你提供的第一个链接,但它无法工作。我使用了在网上找到的MIME类型“text/comma-separated-values”,但浏览器(IE、FF、Chrome)不能正确解释它。 - yves.beutler
如果我使用a4j:components,它就不会工作,但现在我改用<h:commandButton>,它可以正常工作。感谢BalusC提供的又一个好答案! - yves.beutler
不客气。确实,你不能通过ajax下载文件。这也已经在第一个链接中提到了。 - BalusC

0
如果您正在使用JSF 2,您可以使用primefaces。
您可以查看link
如果没有,您可以这样做:
List<Object> report = new ArrayList<Object>(); // fill your arraylist with relevant data 
String filename = "report.csv";    
File file = new File(filename);
Writer output = new BufferedWriter(new FileWriter(file));
output.append("Column1");
output.append(",");
output.append("Column2");
output.append("\n");
//your data goes here, Replcae Object with your bean
for (Object row:report){
    output.append(row.field1);
    output.append(",");
    output.append(row.field2);
    output.append("\n");
}
output.flush();
output.close();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接