Friday Repost: Easy file uploading in Grails
The Friday Repost series are copies from my earlier writings. Since I don’t want to loose them, and they might prove useful to others, I’m reposting them on this blog.
If you want to upload files with Grails, there are multiple ways of doing so. However, there’s at least one way which makes it really easy do so, while keeping the code as clean as possible. This blog describes the steps to take to get the file upload to work, while maintaining a very clean codebase.
To get started, first create a new Grails application by running the following command:
grails create-app imageupload
After you have created your application, create a new file called ‘UploadImageCommand.groovy’ in the src/groovy/com/example/command directory
The UploadImageCommand.groovy should look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.example.command import org.springframework.web.multipart.MultipartFile /** * @author Erik Pragt */ final class UploadImageCommand { MultipartFile contents static constraints = { } } |
Using commands for all changes in the system is usually a good thing. This prevents any malicious code from entering the system, and also describes the
intent of the system by using sensible naming for the commands, in this case ‘Upload Image’.
Now we need two more things: the persistent object (the Domain Object) and the Controller. Actually, I would recommend using a Service for all state changes
of the system, because of the transactional support in services and for providing a uniform way of state changes. However, that’s beyond the scope of this blog, so we’ll
leave it for later and focus on the image uploading for now!
The domain class
To create the domain class, typing in the following:
grails create-domain-class com.example.domain.Image
This creates an Image.groovy file in the grails-app/domain folder. Open the file, and type in the following contents:
1 2 3 4 5 |
package com.example.domain class Image { byte[] bytes } |
Also, create a controller:
grails create-controller com.example.controller.Image
This creates an ImageController.groovy file in the grails-app/controllers folder. Open the file, and type in the following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.example.controller import com.example.domain.* import com.example.command.* class ImageController { def upload = { UploadImageCommand command -> // validation ommited... def image = new Image(bytes:command.contents.bytes) image.save() println "Currently ${Image.count()} images loaded" } } |
Now, all you need is a simple form which will upload your image (or actually any kind of document). The easiest way to do this is create a new file called
upload.gsp and place it in the web-app directory . Make the file look like this:
1 2 3 4 5 6 7 8 9 |
<html> <body> <g:uploadForm controller="image" action="upload" name="myUpload"> <input name="contents" type="file"> <input type="submit" /> </g:uploadForm> </body> </html> |
Now, type grails run-app
And browse to http://localhost:8080/imageupload/upload.gsp
. When you upload a file there, you will see the counter increase in the log file. Clean, fast and easy!
Hmmm, you are missing some setup. http://localhost:8080/imageupload take you to the default Grails scaffolding page not the upload page.
Hi Rob, thanks, I corrected the error by changing the URL to browse to. Better?
Great post, saved me a lot of time!
Thank you, Erik!
Sure, glad I could help!
I wonder, why have you defined static constraints = { } in the UploadImageCommand class? It’s not a Domain class, so it will never be mapped to a database. What am I missing?
You’re right. However, since it’s a Command object, it can be validated, and the validation rules (the constraints) can be put in this block. Hope that helps!