How to create a CSV file using servlet?
csv, java, servlets
Solution
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:
- Fields are separated by a comma.
- If a comma occurs within a field, then the field has to be surrounded by double quotes.
- 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`.
Problem
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?