views:

5168

answers:

5

I'm still learning Grails and seem to have hit a stumbling block.

Here are the 2 domain classes:

class Photo {
    byte[] file 

    static belongsTo = Profile
}


class Profile {
    String fullName
    Set photos

    static hasMany = [photos:Photo]  
}

The relevant controller snippet:

class PhotoController {

..... def viewImage = {

  def photo = Photo.get( params.id )
  byte[] image = photo.file 
  response.outputStream << image

}

...... }

Finally the GSP snippet:

<img class="Photo" src="${createLink(controller:'photo', action:'viewImage', id:'profileInstance.photos.get(1).id')}" />

Now how do I access the photo so that it will be shown on the GSP? I'm pretty sure that profileInstance.photos.get(1).id is not correct. Thanks!!

A: 

As it is a Set, if you want the first element, you will have to go:

profileInstance.photos.toArray()[0].id

or

profileInstance.photos.iterator().next()
Hates_
Yes, the /photo/viewImage/{anyPhotoId} does show a photo correctly. Actually I think I used a Set instead of ArrayList. Is this the cuase of the problem? Thanks!
Walter
@Walter - Ah yes. I have amended my answer.
Hates_
A: 

My guess is you need to set the content type of the response stream. Something like:

response.ContentType = "image/jpeg"

This may or may not need to be before you stream to the response stream (can't imagine that it would matter). I'd just put it before the outputStream line in your code above.

Bill James
I tested this and it doesn't appear to require the contentype setting. Tks.
Walter
+1  A: 

now, i actually think storing the photo as a binary blob in the database isnt the best solution - though you might have reasons why it needs to be done that way.

how about storing the name of the photo (and/or the path) instead? If name clashing issues are probable, use the md5 checksum of the photo as the name. Then the photo becomes a static resource, a simple file, instead of a more complicated and slower MVC request.

Chii
This could be an option. I 'll need to explore it further. Thanks!
Walter
What about securing that image? If you're using a direct URL to the file, you lose the ability to (or make it much more difficult to) secure the image to specific users/roles.
Bill James
@bill: i guess it depends on the requirements. Security will come at a cost, and my method is a bit harder to secure (not impossible, but its probably simpler using other's suggestions if security is important).
Chii
+1  A: 

If you have a url for the image, you just have to make sure you return the appropriate anser in the controller:

  def viewImage= {
    //retrieve photo code here
    response.setHeader("Content-disposition", "attachment; filename=${photo.name}")
    response.contentType = photo.fileType //'image/jpeg' will do too
    response.outputStream << photo.file //'myphoto.jpg' will do too
    response.outputStream.flush()
    return;
  }
Miguel Ping
A: 

id:'profileInstance.photos.get(1).id' should be id:profileInstance.photos.get(1).id. no quota

leroy zhu