Reputation: 122
I would like to permit the client to download a csv file containing data from a ResultSet. I am using the java API (PLAY! 2.1).
My solution works but is not usable when the ResultSet contains a huge amount of data.
In my controller:
ResultSet rs = st.executeQuery(sql);
String filename = "";
filename = createCSV(rs);.
response().setContentType("text/csv");
response().setHeader("Content-disposition","attachment; filename="+"export.csv");
return ok(new java.io.File("D:\\UTILIS~1\\user\\AppData\\Local\\Temp\\"+filename));
createCSV method:
public static String createCSV(ResultSet _resultSet) {
String filename = "";
try{
ResultSetMetaData meta = _resultSet.getMetaData();
// CSV file creation
File tempDir = new File(System.getProperty("java.io.tmpdir"));
System.out.println(System.getProperty("java.io.tmpdir"));
File tempFile = File.createTempFile("test", ".csv", tempDir);
filename = tempFile.getName();
FileWriter fileWriter = new FileWriter(tempFile, true);
System.out.println(tempFile.getAbsolutePath());
BufferedWriter bw = new BufferedWriter(fileWriter);
for(int i = 1; i <= meta.getColumnCount(); i++)
{
String columnLabel = meta.getColumnName(i);
bw.write(columnLabel + "|");
}
bw.write("\r\n");
while(_resultSet.next())
{
for(int i = 1, count = meta.getColumnCount(); i <= count; i++){
if (_resultSet.getObject(i) == null)
bw.write("null|");
else
bw.write(_resultSet.getObject(i).toString() + "|");
}
bw.write("\r\n");
}
bw.close();
tempFile.deleteOnExit();
} catch(Exception e){
e.printStackTrace();
}
return filename;
}
To save memory, how can I write to a file and send it to the user using stream.
I think i need to use Chunks but i am not sure how to do it.
Any samples, hints?
Upvotes: 4
Views: 6076
Reputation: 1973
1) Get the output stream from the response
2) Pass this output stream to the createCSV method and write to it directly
You can also zip the results by decorating the output stream with ZipOutputStream.
Note: there is no need to create a temp file.
Upvotes: 0
Reputation: 1493
You can find a example of chunked response in the documentation:
http://www.playframework.com/documentation/2.1.1/JavaStream
You can send the the csv content while you generate it.
Upvotes: 1
Reputation: 1822
The Ok method takes a byte array as a parameter
So, get a byte array of the contents of the file and try
return ok(s.toByteArray()).as("application/octet-stream");
See this to get a byte array of a file
Upvotes: 1