5

I don't know how to download a CSV file. The CSV will be generated at runtime. Do I need to save the file in the tomcat WEB-INF directory first? I'm using JSF 1.2.

By the way, what's the favored JSF component for this kind of task?


Edit (05.05.2012 - 15:53)

I tried the solution BalusC stated in his first link, but if I click on my commandButton the content of the file is displayed on the webpage. Maybe there's a problem with the mimetype?

xhtml-file:

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

main bean:

    public String doDataExport() {

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

export-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");
    }
}

Edit (05.05.2012 - 16:27)

I solved my problem. I have to use <h:commandButton> instead of <a4j:commandButton> and now it works!

Community
  • 1
  • 1
yves.beutler
  • 972
  • 1
  • 14
  • 32

2 Answers2

4

Do I need to save the file in the tomcat WEB-INF directory first?

No, just write it straight to the HTTP response body as you obtain by ExternalContext#getResponseOutputStream() after having set the proper response headers which tells the browser what it's going to retrieve.

Do the math based on the concrete examples found in the following answers:

Basically:

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

By the way, what's the favorite jsf-component for this kind of task?

This is subjective. But anyway, we're using <p:dataExporter> to full satisfaction.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I don't think that I can use `PrimeFaces`, because they don't support JSF 1.2 since `PrimeFaces 2.0` when I'm right? – yves.beutler May 05 '12 at 12:41
  • 1
    That's correct, the ancient JSF 1.x is near end of life so you shouldn't expect new component library support for it. Just go ahead with streaming it manually. You'd only need to grab the raw `HttpServletResponse` by `ExternalContext#getResponse()` and then calling its `getOutputStream()` instead, but that's already outlined in the 1st link. Or, of course, upgrade to JSF 2. It offers so many advantages over JSF 1.2. – BalusC May 05 '12 at 12:43
  • I know the disadvantages of jsf 1.2, but at the moment we're not able to upgrade to a higher level. I tried to understand your first link, but it doesn't work. I used the mimetype `text/comma-separated-values` I found on the web, but the browsers (IE,FF,Chrome) don't interpret it correctly. – yves.beutler May 05 '12 at 14:20
  • If I use `a4j:components` then it won't work, but now I changed to `` and it works correclty. Thanks BalusC for another great answer! – yves.beutler May 05 '12 at 14:26
  • You're welcome. Indeed, you can't download files by ajax. That's also already mentioned in the 1st link. – BalusC May 05 '12 at 17:46
0

If you are using JSF 2 you can use primefaces.
You can take a look at that link.

If not you can do it like that:

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();
choop
  • 921
  • 2
  • 9
  • 28