Grails可以动态创建可下载的文件

时间:2011-06-07 22:07:35

标签: file grails download on-the-fly

简单地说:我可以创建一个文件,将其保存在文件系统中,然后创建一个带有该文件链接的页面,但是如果我想要一个包含许多文件链接的页面,而这些文件可能不需要全部生成?

所以我的用户点击列表页面上的链接,如:

<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
}

2 个答案:

答案 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选项,则会提示用户下载该文件。)