简体   繁体   中英

How to create a CSV file using servlet?

I want to download a CSV file from a servlet . I have data in the array of objects ( object[] ), I need to write it into CSV and download.

Could you help me how to do this in a servlet class?

How can Object[] ever represent CSV data? Does it contain one row with several columns or several rows with one column? I'd imagine that Object[][] or List<List<Object>> makes more sense.

Anyway, when creating a CSV file you've to adhere the RFC4180 spec . It's basically simple, there are only 3 strict rules:

  1. Fields are separated by a comma.
  2. If a comma occurs within a field, then the field has to be surrounded by double quotes.
  3. If a double quote occurs within a field, then the field has to be surrounded by double quotes and the double quote within the field has to be escaped by another double quote.

Here's a kickoff example which does exactly that based on a List<List<T>> as source and an OutputStream as destination.

public static <T> void writeCsv (List<List<T>> csv, char separator, OutputStream output) throws IOException {
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, "UTF-8"));
    for (List<T> row : csv) {
        for (Iterator<T> iter = row.iterator(); iter.hasNext();) {
            String field = String.valueOf(iter.next()).replace("\"", "\"\"");
            if (field.indexOf(separator) > -1 || field.indexOf('"') > -1) {
                field = '"' + field + '"';
            }
            writer.append(field);
            if (iter.hasNext()) {
                writer.append(separator);
            }
        }
        writer.newLine();
    }
    writer.flush();
}

Here's how you can use it in a Servlet:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    List<List<Object>> csv = getItSomehow();
    response.setHeader("Content-Type", "text/csv");
    response.setHeader("Content-Disposition", "attachment;filename=\"file.csv\"");
    writeCsv(csv, ';', response.getOutputStream());
}

(note that Europe based locales use a semicolon instead of comma for CSV files, feel free to change)

The Content-Disposition of attachment will force a Save As dialogue. Note that MSIE has the misbehaviour that it doesn't take the filename as default filename in the Save As dialogue, but it instead takes the last part of the pathinfo. So if this servlet is for example invoked by http://example.com/csv , then you'll get csv as default filename. Rather append it to the pathinfo like follows http://example.com/csv/file.csv . The servlet should only be mapped on an url-pattern of /csv/* instead of /csv .

Here's an attempt:

public void doGet(HttpServletRequest request,
                HttpServletResponse response)
  throws ServletException, IOException {

    // Other stuff you know that I don't..

    Object[] data = search.getSearch();
    response.setContentType("text/csv");
    PrintWriter out = response.getWriter();
    for (Object d : data) {
        out.println(d.field1 + "," + d.field2 + "," + d.field3 + ...);
    }
}

This broken if your fields have commas for data. I leave you to figure out how to do that since it's a quick Google Search .

There is the JavaCSV which will help you generate the csv representation.

Then you can write the file using:

  • response.getWriter() to print the contents
  • response.setContentType("text/csv")

Here's some (redacted for brevity and generality) code from a production servlet I have running. It should be trivial to swap in your specific data array with the code below.

public void doGet(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException {

        res.setContentType("application/octet-stream");
        res.setHeader("Content-Disposition", "attachment; filename=\"TSR.csv\"");
        try {
            // Write the header line
            OutputStream o = res.getOutputStream();
            String header = "ID,ControlNumber\n";
            o.write(header.getBytes());

            // Write the data lines
            Vector records = getRecords(); // Custom to my app
            Iterator i = records.iterator();
            while (i.hasNext()) {
                                // Custom data object; use your own
                StandardReportDTO sr = (StandardReportDTO) i.next();
                StringBuffer line = new StringBuffer();
                line.append(sr.getID());
                line.append(",");
                line.append(sr.getControlNumber());
                line.append("\n");
                o.write(line.toString().getBytes());
                o.flush();
            }

        } catch (Exception e) {
//          log.error(e);
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM