I want to download csv file from servlet.Data comes from Object[] obj=search.getSearch();
I have data the object[], i need to write into csv and download.
Could you help me how to do in servlet class?
I want to download csv file from servlet.Data comes from Object[] obj=search.getSearch();
I have data the object[], i need to write into csv and download.
Could you help me how to do in servlet class?
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.
Depending on how complicated your data is, if your data is simple, you might as well create the comma-delimited string yourself.
If your data consist of "unsafe characters", like double quotes or commas, it is much easier to rely on some libraries like opencsv or ostermiller's version to construct the csv string for you.
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);
}
}
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:
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) {
StringBuilder line = new StringBuilder();
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 + '"';
}
line.append(field);
if (iter.hasNext()) {
line.append(separator);
}
}
writer.write(line.toString());
writer.newLine();
}
}
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());
}
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
.