Grails : Upload and Render File
Lets discuss how can we upload a file and store it in a database, along with that how do we render it on the gsp page. I am taking an example to upload and render the image in this blog, though the code would be same for any other file.
So Lets consider I have a domain class with the name Person
class Person {
.
.
.
bytes[] picture
static constraints = {
picture(size:0..5000000) // to store files upto 5MB approx
}
}
Once we have a field with a byte[] defined in the class then automatically its view is generated with a input tag of file type in html, which returns the MultipartFile object in the controller. MultipartFile provides various useful methods which can be used getBytes(), getSize(), getContentType(), getName() etc.
So as MultipartFile object returs the byte[] which is to be stored in a picture property of a person class, in the save action of the PersonController Lets see how we do it :
person.picture = params.picture
or
person.properties = params
//Now the person object holds the image and lets save it
person.save()
We are done with file uploading. Now to render the image/file, lets have a separate controller in a controller directory, where we would define the action to generate the image:
class ImageController { def defaultAction ='show'
def show= {
//loads the class with a name and assigns obj a new instance created of the same object
def obj = Class.forName("${params.classname}",true,Thread.currentThread().contextClassLoader).newInstance();
def object = obj.get( params.id )
response.setContentType(params.mime)
byte[] image = object."${params.fieldName}"
response.outputStream << image
}
}
Now where ever we want to display the image, we can just include the following tag:
Note : The above code can be dangerous as a hacker can modify the className and feildName in the query string and get the hidden information.
Hope this helped.
~Amit Jain~
amit@intelligrape.com
I create form and i want to save details of my form in file which i entered from front end how i do in grails
Hi Amit
i have uploaded the PDF file and saved into the database byte[] document), i want that the uploaded pdf should show on GSP inside the particular div. how can i do that? please help
Hi Anuj,
For displaying file in a div, it looks like it is no different than image then. Can we not render this file as an image? See stackoverflow.com/questions/4502278/grails-displaying-created-image-in-gsp how can we do that. Let me know if this doesn’t work.
Thanks,
Hi Amit i want to store image in file system it is working fine on local system but when i upload image on prod environment it show me error java.io.FileNotFoundException: . Could you help me please.
Thanks
Hi Amit,
Just wanted to mention, that image previews cannot be done in a cross browser fashion, using the approach suggested by you. IE will never allow the application to reference the local file, same applies for chrome. Only cross browser way of showing image previews is to use, ajax based file upload and then sending the image back as base64 encoded string.
Hope that helps someone.
@Amit Jain
Thank you sir for your quick response. Can you post the code snippet or any example to show.I am novice to grails and don’t have experience with javascript.
Yes you can. For that you can use javascript to add “img” tag dynamically and keep its source as taken from file input box value. This script can be executed on lost focus of file input box.
Can I view the image before saving to database to confirm that the image I am uploading is the right one.
using byte will give a tinyblob in the database of which cannot accommodate a larger picture
Thanks Alessio & bald for bringing out the loopholes in the code. If you could find the solution then please share.
And yes we need to provide the content type, which I have updated in the blog now.
Thanks Amit for showing how easy and fast is implementing (prototyping) file upload in Grails.
Would be better in a real scenario to use a general domain class such as document, file or image? You can also save other useful information for categorizing (size, mime, etc)
Also this type of controller action seems quite risky.
Thanks for posting this, Amit! I found it very useful.
Isn’t it a little dangerous? I.e. what if i call the controller specifying potentially dangerous Class/method combinations?
Furthermore, how’s the client able to determine the content type without specifying it?
Regards,
Alessio