Grails+Dojo Ajax 文件上传





5.00/5 (2投票s)
Grails+Dojo Ajax 文件上传
我目前正在开发一个 Grails 应用,需求是上传产品图片,然后将其调整为不同尺寸的缩略图,用于不同的购物页面。由于实现这个功能花了一些功夫,我想在这里分享我的解决方案,以备不时之需。
首先,为了做好准备,我已经将应用程序升级到最新发布的 Grails 1.1。
一开始,我天真地尝试使用内置的 Prototype 库通过一个简单的 <g:submitRemote/>
标签来完成上传。你可能已经猜到,这根本不起作用。继续摸索(而且没有阅读手册),我将这个问题提交给了 Grails 项目。Graeme 非常礼貌地告诉我,这是已知且预期的行为,因为 Prototype 不支持这种功能。然而,也是 Graeme 提示我尝试 Dojo。
于是,我继续安装了 Grails Dojo 插件。安装完成后,据说只需要一个 <g:javascript library="dojo"/>
就可以将你的 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)
}
}
就这样!请告诉我你对这个解决方案的看法。它对我来说绝对有效。你会注意到我没有包含上传进度条 - 我会在项目的未来迭代中实现这个功能。祝好!