65.9K
CodeProject 正在变化。 阅读更多。
Home

Grails+Dojo Ajax 文件上传

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2009年4月14日

CPOL

2分钟阅读

viewsIcon

26551

Grails+Dojo Ajax 文件上传

我目前正在开发一个 Grails 应用,需求是上传产品图片,然后将其调整为不同尺寸的缩略图,用于不同的购物页面。由于实现这个功能花了一些功夫,我想在这里分享我的解决方案,以备不时之需。

首先,为了做好准备,我已经将应用程序升级到最新发布的 Grails 1.1

一开始,我天真地尝试使用内置的 Prototype 库通过一个简单的 <g:submitRemote/> 标签来完成上传。你可能已经猜到,这根本不起作用。继续摸索(而且没有阅读手册),我将这个问题提交给了 Grails 项目。Graeme 非常礼貌地告诉我,这是已知且预期的行为,因为 Prototype 不支持这种功能。然而,也是 Graeme 提示我尝试 Dojo。

于是,我继续安装了 Grails Dojo 插件。安装完成后,据说只需要一个 <g:javascript library="dojo"/&gt; 就可以将你的 Ajax 调用从 Prototype 转换为 Dojo。但对我来说并非如此,到处都出现了 JavaScript 错误,其中最主要的是 dojo.js 似乎被插件安装到了一个意外的位置。我直接将它复制到了预期的位置并继续前进。然而,当我尝试使用 Dojo 的文件上传支持时,我发现插件附带的 Dojo 版本看起来落后很多。对此感到沮丧,我直接卸载了 Dojo 插件,并安装了 最新版本(截至目前是 1.2.3),然后开始开发我的解决方案。

开始吧

1. 在你的 GSP 中添加必要的 Dojo 依赖

<script type="text/javascript" src="${createLinkTo(dir: 'js/dojo', file: 'dojo.js')}"
   djConfig="parseOnLoad:true, isDebug:true"></script>
<g:javascript>
   dojo.require("dojo.io.iframe");
</g:javascript>

2. 使用 dojo.io.iframe 编写一个函数来发送表单

function submitForm() {
   dojo.io.iframe.send({
      form: 'uploadProductImageForm',
      load: function (data) {
         dojo.byId('productImage').innerHTML = data;
      }
   });
}

3. 创建文件上传表单

<g:form name="uploadProductImageForm" 
method="post" action="uploadProductImage"
    enctype="multipart/form-data">
   <input type="hidden" name="id" value="${productInstance?.id}"/>
   <input type="file" name="newProductImage"/>
   <span class="button"><input class="add" 
   type="button" name="uploadImage"
    value="Upload Image" onclick="submitForm()"/></span>
</g:form>

4. 创建控制器方法

def uploadProductImage = {
   def f = request.getFile('newProductImage')
   if (!f.empty) {

   def imagePath = grailsApplication.config.store.productImages.location

   //Create unique name for this image set based on current timestamp
   def name = "image" + new Date().getTime()

   //Store the file
   def file = new File("${imagePath}/${originalFilename}")
   f.transferTo(file)

   //Do some image processing (resizing, etc.)
   ...

   //Dojo requires returning the result nested in an HTML document containing
   //a body and textarea tag. Do this with
   //Groovy's built-in MarkupBuilder

   def writer = new StringWriter()
   def xml = new MarkupBuilder(writer)

   xml.html {
     body {
       textarea {
         img(src: resource(dir: grailsApplication.config.store.productImages.webPath,
            file: product.mediumImage.name), width: '250')
       }
     }
   }

   render writer.toString()
   }
   else {
      flash.message = 'file cannot be empty'
      redirect(action: show)
   }
}

就这样!请告诉我你对这个解决方案的看法。它对我来说绝对有效。你会注意到我没有包含上传进度条 - 我会在项目的未来迭代中实现这个功能。祝好!

© . All rights reserved.