简单地说:我可以制作一个文件,将其保存在文件系统中,然后制作一个带有该文件链接的页面,但如果我想要一个带有许多文件链接的网页,而这些文件可能不需要全部生成,该怎么办?
所以我的用户点击列表页面上的链接,比如:
<g:link action="gimmeAFile" id="${myThingieInstance.id}">${fieldValue(bean: myThingieInstance, field: "id")}</g:link>
现在我有一个控制器,看起来像这样:
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]
}
然后他们转到gimmeAFile.gsp,它有实际下载文件的链接:
<a href="${resource(dir:'tmpfiles',file:fileName)}">Download Report</a>
如何在列表查看器上创建一个链接,该链接将创建和下载文件,而不将用户拖到额外的屏幕上。注意:我无法预先生成文件,所以我需要弄清楚如何链接到一个还没有的文件。我在控制器的末尾想一些类似render()的东西。我可以让gimmeAFile控制器只提供文件,而不是制作一个带有文件链接的页面吗?
好的,所以澄清一下,这是我根据卡莱布的回答最终得出的结论。谢谢!!
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
}
}
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
}
您可以创建一个视图,只获取文件的字节数并写入响应:
response.contentType = 'image/jpeg' // or whatever content type your resources are
response.outputStream << file.getBytes()
response.outputStream.flush()
这就是你想做的吗?
另一个更好的选项是,您可以直接从控制器的操作中渲染文件:
render(file: theFile, contentType: 'your/contentType')
另请参阅:http://grails.org/doc/latest/ref/Controllers/render.html
(我发现,如果添加fileName
选项,它会提示用户下载文件。)