简单地说:我可以创建一个文件,将其保存在文件系统中,然后创建一个带有该文件链接的页面,但是如果我想要一个包含许多文件链接的页面,而这些文件可能不需要全部生成?
所以我的用户点击列表页面上的链接,如:
<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控制器只提供文件,而不是创建一个带有文件链接的页面吗?
好的,为了澄清这是我最终根据Kaleb的答案弄清楚的。谢谢你!!
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
}
答案 0 :(得分:3)
您可以创建一个只获取文件字节并写出响应的视图:
response.contentType = 'image/jpeg' // or whatever content type your resources are
response.outputStream << file.getBytes()
response.outputStream.flush()
这是你想要做的吗?
答案 1 :(得分:3)
另一个更好一点的选项,你可以直接从控制器的动作渲染文件:
render(file: theFile, contentType: 'your/contentType')
另请参阅:http://grails.org/doc/latest/ref/Controllers/render.html
(我发现如果您添加fileName
选项,则会提示用户下载该文件。)