Render in CSV format in grails
Grails provides Converter class to quickly transform any kind of Java/Groovy objects to either XML/JSON response. Like,
render obj as XML
or
render obj as JSON
I am working on a grails app that requires me to render an object in csv format. Is there a way to do that?
I tried out few stuff and I have explained those below:
Snippet of my code
csv {
def results = []
for(d in Data.list()) {
def r= [d.id, d.name]
results << r
}
def result = ''
results.each{ row ->
row.each{
col -> result += col + ','
}
result = result[0..-2]
result += '\n'
}
println result
render(contentType:'text/csv',text:result)
}
I store开发者_运维知识库d my results in an ArrayList and then converted them to a comma separated string and then passed it to a render method. When I run the above code on the browser, it creates the desired file and the browser pops up a dialog box to "Save As" the file.
When I changed the contentType to text/html, the file contents are displayed on the browser with no newline chars.
Is there a better way to render the contents of the csv file on the browser the same way its on the file.
Thanks.
So I was just trying to solve the same problem -- responding to a Grails 3 request with a CSV download.
I got a tip from the Grails slack channel to use the Apache Commons CSV code which takes care of the details like handling commas, quotes and other special characters.
To use it, you'll need to add it to your project's dependencies. In build.gradle
, under dependencies
add:
compile "org.apache.commons:commons-csv:1.2"
Here's an example controller that puts everything together and responds to all requests with the CSV download for the domain object Item
.
package name.of.package
import grails.rest.*
import grails.converters.*
import org.apache.commons.csv.CSVFormat
import org.apache.commons.csv.CSVPrinter
class ItemController extends RestfulController {
static responseFormats = ['json', 'xml', 'csv']
ItemController () {
super(ApprovedHotel)
}
def export(Integer max) {
def items = Item.list()
withFormat {
csv {
def results = []
for(d in items) {
def r= [d.column1, d.column2]
results << r
}
StringWriter stringWriter = new StringWriter();
CSVPrinter printer = new CSVPrinter(stringWriter, CSVFormat.EXCEL);
printer.printRecords( results )
printer.flush()
printer.close()
result = stringWriter.toString()
response.setHeader("Content-disposition", "attachment; filename=filename.csv")
render(contentType:'text/csv',text:result)
}
}
}
}
You can render the CSV as text/plain
instead of text/html
. Browsers will render this as plain text, similar to what you'd see if you open the file in an editor.
If you want to display csv data in the browser you need to use
<br>
instead of \n for a new line if you want new lines to be displayed properly in HTML. Browsers generally ignore control characters and only base formatting on HTML tags.
If you want to allow the user to download a csv file code like the following will work.
response.setHeader("Content-disposition", "attachment; filename=Edata.csv")
render(contentType: "text/csv", text:varContainingData )
精彩评论