views:

1070

answers:

3

I want to upload an image using a groovy on grails. My gsp page is as follows (I am showing a simplified version of the original)

<g:form controller="post" action="save" enctype="multipart/form-data">        
      My picture  <input type="file" name="myPicture" />     
    <g:submitButton name="submit" value="Save"/>
</g:form>

My domain class is as follows:

class Post {    

byte[] myPicture

static mapping = {
    myPicture type:  "blob" 
}

I need this mapping otherwise MySql will create a smallblob which is to small to fit the images

static constraints = {
    myPicture(nullable:false)      
}

}

At the controller I have an action called save which is as follows:

def save = {                               
    def post = loadPost(params.id)

    post.properties = params

    if(post.save()) {
        print "hallo world"          
        redirect(action:'list', params:params)
    } else {
        render(view:'edit', model:[post:post])
    }
}

The exception is thrown when I try to save the image at the DB.

2009-04-27 18:16:07,319 [20806951@qtp0-0] ERROR errors.GrailsExceptionResolver  - java.lang.ClassCastException: [B cannot be cast to java.sql.Blob

org.codehaus.groovy.runtime.InvokerInvocationException: java.lang.ClassCastException: [B cannot be cast to java.sql.Blob

Any hint why is this?

BTW, I've seen in a tutorial that images were handled as strings but it didn't work as well.

+2  A: 

I found a similar question on Nabble:

http://www.nabble.com/MySQL-and-Blobs-td16116885.html

Two possible solutions are suggested:

  • Change the constraints of the blob property to a large max-size, to stop it from using "TinyBlob".
  • Use the Hibernate Blob implementation instead of byte[] for the property's type declaration. This will require you stream data into the Blob, instead of direct assignment, but the post above gives code to do so.
Bill James
Thanks. This is the solution for the class cast exception
Luixv
+2  A: 

Can you try using Spring's MultipartFile within your loadPost() method?

Here's an example from the docs:

def upload = {
    def f = request.getFile('myFile')
    if(!f.empty) {
      f.transferTo( new File('/some/local/dir/myfile.txt') )
      response.sendError(200,'Done');
    }    
    else {
       flash.message = 'file cannot be empty'
       render(view:'uploadForm')
    }
}

I believe you can access f.bytes directly.

Miguel Ping
Thanks for your advice. getBytes() should be used. anyway this doesn't solve the ClassCastException. For solving this problem see @Bill James answer
Luixv
As a side note, I think f.bytes is equivalente to f.getBytes(), since groovy dispatch the property access to the getter.
Miguel Ping
Thanks again. I will test it. I thought I've tried but I got an exception. Let's see.
Luixv
+1  A: 

try this way:

  def save = {                               

    def post = loadPost(params.id)

    def f = request.getFile('myPicture')             

    post.myPicture = f.getBytes()
    post.pictureType = f.getContentType()                    


    if(post.save()) {
al