fdubrez
fdubrez

Reputation: 122

Export csv file using stream with Play 2.1

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

Answers (3)

Lluis Martinez
Lluis Martinez

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

Marco
Marco

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

Tapan Nallan
Tapan Nallan

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

Related Questions