Grails create downloadable file on the fly
Briefly: I can make a file, save it in the file system and then make a page with a link to that file, but what if I want a page with links to many files which may not all need to be generated?
So my user clicks a link on the list page like:
<g:link action="gimmeAFile" id="${myThingieInstance.id}">${fieldValue(bean: myThingieInstance, field: "id")}</g:link>
Right now I have a controller that looks like this:
def gimmeAFile = {
def lotsaLines = []
//Do a ton of stuff that has lotsaLines.add(resultStrings) all over
def fileName = "blahblah-${dateOrSomething}.csv"
def dumbFile = new File('web-app/tmpfiles/'+fileName).withWriter {out ->
lotsaLines.each{
out.println it
}
}
[fileName:fileName]
}
And then they go to gimmeAFile.gsp which has the link to actually download the file:
<a href="${resource(dir:'tmpfiles',file:fileName)}">Download Report</a>
How do I make a link on the list viewer that will create and download the file without dragging the user to an extra screen. NOTE: I cannot have the files pre-generated, so I need to figure out how to link to a file that isnt there yet. I'm thinking something like render() at the end of the controller. Can I make the gimmeAFile controller just give the file instead of making a page with a link to the file?
OK so to clarify this is what I finally figured out based on Kaleb's answer. Thankyou SO!!
def gimmeAFile = {
def lotsaLines = []
//Do a ton of stuff that has lotsaLines.add(resultStrings) all over
def开发者_JAVA技巧 fileName = "blahblah-${dateOrSomething}.csv"
def dumbFile = new File('web-app/tmpfiles/'+fileName).withWriter {out ->
lotsaLines.each{
out.println it
}
}
def openAgain = new File('web-app/tmpfiles/'+fileName)
response.setContentType("text/csv")
response.setHeader("Content-disposition", "filename=${fileName}")
response.outputStream << openAgain.getBytes()
response.outputStream.flush()
return
}
You can create a view that just gets the bytes of the file and writes out to the response:
response.contentType = 'image/jpeg' // or whatever content type your resources are
response.outputStream << file.getBytes()
response.outputStream.flush()
Is that what you're trying to do?
Another option which is a bit nicer, you can just render the file, straight from your controller's action:
render(file: theFile, contentType: 'your/contentType')
See also: http://grails.org/doc/latest/ref/Controllers/render.html
(I've found that if you add the fileName
option, it prompts the user to download the file.)
精彩评论