Displaying image object from controller in the bro

2019-01-18 16:34发布

问题:

I use playframework 2.2.1 with Java,
I am trying to pass BufferedImage or ByteArray or ByteArrayInputStream
to view template in order to display it in browser directly from memory,
without saving to server storage.
in my view template I request an image:

<img src="@{Application.getImage()}"/>

my Application controller:

public static Result getImage() throws IOException{  
    BufferedImage image = ImageIO.read(new File("public/img/1.jpg"));  
    //some image manipulations  
    ByteArrayOutputStream baos = new ByteArrayOutputStream();  
    ImageIO.write(image, "jpg", baos);  
    return ok(baos.toByteArray()).as("image/jpg");  
}

in generated html I get:

<img src="SimpleResult(200, Map(Content-Type -&gt; image/jpg))">

I've found some info about this topic (one, two, three, four),
but it is usually related to older versions, or Scala versions of play.
Please suggest anything or point to my mistake,
Thanks

回答1:

You should use a route to getImage() action instead of its Result in src attribute:

<img src='@routes.Application.getImage()'/>

BTW: Although we don't know what kind of manipulation you do with images, sometimes it makes sense to save them to disc - especially if there is possibility that they will be reused. In such case you can return it with:

return ok(new File("/path/to/file"));

Of course still with usage of route as src ;)



回答2:

For byte array images here's my solution (based on other solutions in stackoverflow):

The Controller:

public static Result getImage(Long id) {
    Entity entity = Entity.find.byId(id);
    ByteArrayInputStream input = null;

    if (entity.getImage() != null) {
        input = new ByteArrayInputStream(entity.getImage());
    } else {
        try {
            byte[] byteArray;
            File file = Play.getFile("/public/images/no_photo.jpg", Play.current());
            byteArray = IOUtils.toByteArray(new FileInputStream(file));
            input = new ByteArrayInputStream(byteArray);
        } catch (Exception e) {

        }
    }

    return ok(input).as("image/jpeg");
}

The routes file:

GET     /entity/image/:id       controllers.Entities.getImage(id:Long)

The view:

<img src=@{routes.Entities.getImage(entity.getId())}>


回答3:

While it is possible to embed images directly into HTML documents, it's not supported by all browsers. To do it, you need to encode the image as Base64. The resulting image will be 33% larger after encoding than it would have been if you served it normally, and won't be cacheable, so unless the image is very small, you'll get worse performance than serving it up normally. I've used this before for emoticons and other very small graphics. I wouldn't use it for anything larger.

You can read more about the pros and cons here:

Should I embed images as data/base64 in CSS or HTML

To implement this, you need to write a method that returns a String, not a Result, and that String needs to look something like this:

data:image/jpg;base64,<base64 encoded image here>