首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

精通 Grails 文件上传和 Atom 联合(3)

精通 Grails 文件上传和 Atom 联合(3)

显示上传的文件如果不将上传的文件在某个地方显示出来,那有何意义呢?打开 grails-app/views/entry/_entry.gsp,添加清单 11 中的代码:
清单 11. 用于显示上传的图像的 GSP 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div class="entry">
  <span class="entry-date">
      <g:longDate>${entryInstance.lastUpdated}</g:longDate> : ${entryInstance.author}
  </span>
  <h2><g:link action="show" id="${entryInstance.id}">${entryInstance.title}</g:link></h2>
  <p>${entryInstance.summary}</p>

  <g:if test="${entryInstance.filename}">
    <p>
      <img src="${createLinkTo(dir:'payload/'+entryInstance.author.login,
                               file:''+entryInstance.filename)}"
           alt="${entryInstance.filename}"
           title="${entryInstance.filename}" />
    </p>
  </g:if>
</div>




由于上传文件是可选的,我将输出包含在一个 <g:if> 块中。如果 entryInstance.filename 字段被填充,则在一个 <img> 标记中显示结果。
图 2 显示新的列表,同时还在显眼的地方显示上传的 Grails 徽标:
图 2. 显示上传的图像但是,如果用户上传其他东西,而不是图像呢?这时就不是将更多的逻辑放入到 GSP 中了,最好的地方是一个定制的 TagLib。
创建 TagLibBlogito 在 grails-app/taglib 中已经有两个 TagLib:DateTagLib.groovy 和 LoginTagLib.groovy。在一个 TagLib 中可以定义任意数量的定制标记,但是这一次我建议创建一个新的 TagLib,以便按语义将标记分组。在命令提示符下输入 grails create-tag-lib Entry,并添加清单 12 中的代码:
清单 12. 创建 displayFile 标记
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class EntryTagLib {

  def displayFile = {attrs, body->
    def user = attrs["user"]
    def filename = attrs["filename"]

    if(filename){
      def extension = filename.split("\\.")[-1]
      def userDir = "payload/${user}"

      switch(extension.toUpperCase()){
        case ["JPG", "PNG", "GIF"]:
             def html = """
             <p>
               <img src="${createLinkTo(dir:''+userDir,
                                        file:''+filename)}"
                    alt="${filename}"
                    title="${filename}" />
             </p>
             """

             out << html
             break

        case "HTML":
             out << "p>html</p>"
             break
        default:
             out << "<p>file</p>"
             break
      }
    }else{
      out << "<!-- no file -->"
    }
  }

}




不久后可以看到,该代码创建一个 <g:displayFile> 标记,该标记需要两个属性:user 和 filename。如果 filename 属性被填充,则取得文件扩展名,并将其转换为大写形式。
Groovy 中的 Switch 语句比 Java 中的对等物的灵活性要大得多。首先,可以在 String 上进行切换(而 Java 语言只能在 int 上进行切换)。更令人惊奇的是,case 既可以指定一个条件列表 List,也可以指定单个的条件。
有了这个 TagLib 后,可以大大简化 _entry.gsp 局部模板,如清单 13 所示:
清单 13. 简化的局部模板
1
2
3
4
5
6
7
8
9
10
11
<div class="entry">
  <span class="entry-date">
      <g:longDate>${entryInstance.lastUpdated}</g:longDate> : ${entryInstance.author}
  </span>
  <h2><g:link action="show" id="${entryInstance.id}">${entryInstance.title}</g:link></h2>
  <p>${entryInstance.summary}</p>

  <g:displayFile filename="${entryInstance.filename}"
                 user="${entryInstance.author.login}" />

</div>




重新启动 Grails,并再次上传 Grails 徽标。在添加对其他文件类型的支持之前,应该确保 TagLib 重构没有破坏已有的功能。
现在,可以确信仍可以上传图像。接下来就是添加对其他文件类型的支持,这只需在 switch 块中实现适当的 case。清单 14 演示如何处理上传的 HTML 文件,以及为默认的 case 创建一个链接来下载该文件:
清单 14. 完整的 switch/case 块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class EntryTagLib {

  def displayFile = {attrs, body->
    def user = attrs["user"]
    def filename = attrs["filename"]

    if(filename){
      def extension = filename.split("\\.")[-1]
      def userDir = "payload/${user}"

      switch(extension.toUpperCase()){
        case ["JPG", "PNG", "GIF"]:
             //SNIP
             break

        case "HTML":
             def webRootDir = servletContext.getRealPath("/")
             out << new File(webRootDir+"/"+userDir, filename).text
             break
        default:
             def html = """
             <p>
               <a href="${createLinkTo(dir:''+userDir,
                                       file:''+filename)}">${filename}</a>
             </p>
             """
             out << html
             break
      }
    }else{
      out << "<!-- no file -->"
    }
  }

}




创建两个新的文本文件,以便测试这个新的行为:一个名为 test.html,另一个名为 noextension。将清单 15 中的内容添加到适当的文件中,上传该文件,确认 TagLib 是否按预期显示每个文件:
清单 15. 用于上传的两个示例文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//test.html
<p>
This is some <b>test</b> HTML.
</p>

<p>
Here is a link to the <a href="http://grails.org">Grails</a> homepage.
</p>

<p>
And here is a link to the
<img src="//grails.org/images/grails-logo.png">Grails Logo</img>.
</p>



//noextension
This file doesn't have an extension.




Web 浏览器看上去应该如图 3 所示:
图 3. 显示所有 3 种类型的上传的文件
返回列表