More image uploading: ImageTools, Transients and Grails
Something that I have come across in my experimentation with Grails is the need to have UI elements in the screen that map to more complex elements in the domain model or things that are not stored in the database. I really like the automagic generation of view elements in Grails GSP files, and have used transient properties to generate views that allow for uploading files. In this post, I will discuss how I used the transient property to enable image uploading in Grails.
One of the ways in which transient properties can be used is to generate the file upload components within the GSP needed to do file uploading. For one of my projects, I needed to allow users to upload an image that I would then save to disk and display. I took a look at the file upload abilities in Grails and liked it, but wasn’t too convinced this would be the most elegant way to go. I didn’t like the manual adding of the form objects in the CRUD generated GSPs since I would often overwrite the generated ones by accident.
The application I am building is basically a series of recipes with a picture that went with each. The image needed to be scaled to one size, and saved to a specific directory.
The solution I came up with involved using the Transient property within my Recipe class, so my domain class looks something like this:
class Recipe {
byte[] image
String imageURL
static transients = ["image"]
}
When I generated the views, the byte[] image will ensure that the image button gets generated into a file browser. In my update and save methods of the controller, I call this
if( recipe.image != null)
recipe = updateImage( recipe )
I use the imageTools plugin in grails to resize my images, and define two new properties in my conf/Config.groovy to set the thumbnail size and download directory.
I defined a new method called image upload:
def updateImage( Recipe recipe ){
// define image tools component
def imageTool = new ImageTool()
// load uploaded byte array
imageTool.load(recipe.image)
// resize image
imageTool.thumbnail( grailsApplication.config.imageTools.thumbsize )
File saveLocation = grailsAttributes.getApplicationContext().getResource( File.separator + grailsApplication.config.imageTools.savelocation ) .getFile()
saveLocation.mkdirs()
File tempfile = File.createTempFile( “recipe”, “.jpg”, saveLocation )
// save resized thumbnail
try{
imageTool.writeResult( tempfile.getAbsolutePath(), “JPEG”)
} catch( Exception e ){
}
return recipe
}
Hi
I am trying to upload files using grails.
Did you have to specify the property action in your form tag ?
()
I notice that with that the controller is not able to handle the to the right closure.
Thanks
spcmdr
June 17, 2008 at 12:48 am
This should work with the grails generated views, as it simply uses Grails scaffolding to handle the file upload. The trick here is to just attach a byte[] to the field to be uploaded and mark it as transient, since it will allow you to take the file.
So this is a simple save() call on the edit.gsp view that gets generated.
tomas
June 17, 2008 at 3:37 am
Could you please tell, what chances in the conf-file you have done?
thx
Joerg
July 4, 2008 at 8:55 pm
There are no changes to conf-file. The only thing that I added so that it can be overwritten later is the destination directory and image thumb size:
imageTools.savelocation = “myuploads”
imageTools.thumbSize = 400
Tomas Lin
July 6, 2008 at 12:36 am
Hi thanks for this post, very useful. I seem to be getting an error around this line:
File tempfile = File.createTempFile( “employee”, “.jpg”, saveLocation )
Which reads: java.io.IOException: The filename, directory name, or volume label syntax is incorrect
In my config file i have added: imageTools.saveLocation = “images”, to match the images folder under web-app in my grails application.
Do you have any idea what the error might be?
Christian Hepworth
July 7, 2008 at 2:12 pm
it might be that your imageTools.savelocation is not set correctly — in my previous comment, I mistyped savedlocation as savedLocation — also check permissions.
Tomas Lin
July 7, 2008 at 3:15 pm
Did you have to change the generated view to remove the multi-part encoding? Or, did yours generate as a normal form?
Les
July 23, 2008 at 5:38 pm
No changes to generated views…
Tomas Lin
July 23, 2008 at 5:47 pm
Hi, Thanks for this post.
I do have a problem, running Grails 1.0.3.
When you edit and update, is causes a 405, method not allowed message.
any ideas on that, I have not changed anything in the views.
Si-mon
July 28, 2008 at 11:43 am
can i get your example app??
don
January 7, 2009 at 9:24 pm
this is great! That ImageTool plugin is unbelievably easy to use! THANKS!
mikecroteau
May 16, 2009 at 12:33 am
Hi
I’m trying to incorporate this plugin, but when i do the writeResult i catch the exception:
ava.lang.IllegalArgumentException: operation “Encode” requires 1 source object(s).
any ideas?
Thanks for the help
Nate
July 1, 2009 at 5:39 pm