Pass Base64 encoded byte [] as a JSON MIME Type

2019-08-24 18:32发布

问题:

I have a REST service which @Produces(MediaType.APPLICATION_JSON). In the REST service, I have created an Image of type BufferedImage and then writing it to ImageIO as a png image. Next, I am encoding this Image as Base64 encoded string. Now I need to return this encoded string in JSON Format and then at the Client side I need to use the Base64 string in img tag as below :

<img id="captchaImage" src="data:image/png;base64,<%=Base64ImageString%>"/>

How I can pass the Base64 as MediaType.APPLICATION_JSON

Code :

import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Base64;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

@RestService
@Named("CaptchaServlet")
@Path("/reCaptchaImg")
@Produces(MediaType.APPLICATION_JSON)
public class CaptchaServlet implements ICaptchaServlet{

    @Override
    public Response processRequest(HttpServletRequest request) throws GeneralSecurityException, IOException {
        try {
        System.out.println("shaan Inside processRequest");
        int width = 150;
        int height = 50;

        //Random string generation happens
        Random r = new Random();
        int length = 6;
        System.out.println("shaan Creating string parameter");
        StringBuffer captchaStringBuffer = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int baseCharNumber = ((r.nextInt((500-1)+1)+1) % 62);
            int charNumber = 0;
            if (baseCharNumber < 26) {
              charNumber = 65 + baseCharNumber;
            }
            else if (baseCharNumber < 52){
              charNumber = 97 + (baseCharNumber - 26);
            }
            else {
              charNumber = 48 + (baseCharNumber - 52);
            }
            captchaStringBuffer.append((char)charNumber);
        }
        String captchaString = captchaStringBuffer.toString();
        System.out.println("The random string generated is : "+captchaString);

        char[] s3 = captchaString.toCharArray();
        System.out.println("shaan1");

        //Converting Captcha String to Image
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = bufferedImage.createGraphics();
        System.out.println("shaan2");
        Font font = new Font("Georgia", Font.BOLD, 18);
        g2d.setFont(font);
        System.out.println("shaan3");
        RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        System.out.println("shaan4");
        rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHints(rh);
        System.out.println("shaan5");
        GradientPaint gp = new GradientPaint(0, 0, Color.red, 0, height / 2, Color.black, true);
        g2d.setPaint(gp);
        g2d.fillRect(0, 0, width, height);
        g2d.setColor(new Color(255, 153, 0));
        System.out.println("shaan6");
        String captcha = String.copyValueOf(s3);
        System.out.println("shaan7");
        int x = 0;
        int y = 0;
        for (int i = 0; i < s3.length; i++) {
            x += 10 + (Math.abs(r.nextInt()) % 15);
            y = 20 + Math.abs(r.nextInt()) % 20;
            g2d.drawChars(s3, i, 1, x, y);
        }
        g2d.dispose();
        System.out.println("shaan8");
        System.out.println("shaan9");

        //Sending Image in output
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "png", baos);
        byte[] imageData = baos.toByteArray();
        System.out.println("shaan10" + captcha);
        request.getSession().setAttribute("captcha", captcha);
        System.out.println("shaan11");
        baos.flush();
        baos.close();
        System.out.println("shaan12");
        System.out.println("The imageData is :"+imageData);

        //Encoding to Base64
        byte[] encoded = Base64.getEncoder().encode(imageData);
        System.out.println("The encoded is :"+encoded);
        return Response.ok(encoded, MediaType.APPLICATION_JSON).build();
        }catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("In Error Catch block");
            e.printStackTrace();
            return Response.status(Status.BAD_REQUEST).build();
        }
}

Just for reference the output of the lines in the code is :

System.out.println("The imageData is :"+imageData);
The imageData is :[B@238bbb96

System.out.println("The encoded is :"+encoded);
The encoded is :[B@1a477e17

回答1:

I think what you are trying to do can't work it also it doesn't make sense for me.

Data-URIs are meant to have the data for the image directly inside the HTML, not to be linked from external URLs.

You should just return the image without encoding it to Base64 and link it directly.

You could change your code to this:

import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

@Named("CaptchaServlet")
@Path("/reCaptchaImg")
@Produces("image/png")
public class CaptchaServlet {

    @GET
    public Response processRequest(@Context HttpServletRequest request) {
        try {
            System.out.println("shaan Inside processRequest");
            int width = 150;
            int height = 50;

            //Random string generation happens
            Random r = new Random();
            int length = 6;
            System.out.println("shaan Creating string parameter");
            StringBuffer captchaStringBuffer = new StringBuffer();
            for (int i = 0; i < length; i++) {
                int baseCharNumber = ((r.nextInt((500 - 1) + 1) + 1) % 62);
                int charNumber = 0;
                if (baseCharNumber < 26) {
                    charNumber = 65 + baseCharNumber;
                } else if (baseCharNumber < 52) {
                    charNumber = 97 + (baseCharNumber - 26);
                } else {
                    charNumber = 48 + (baseCharNumber - 52);
                }
                captchaStringBuffer.append((char) charNumber);
            }
            String captchaString = captchaStringBuffer.toString();
            System.out.println("The random string generated is : " + captchaString);

            char[] s3 = captchaString.toCharArray();
            System.out.println("shaan1");

            //Converting Captcha String to Image
            BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = bufferedImage.createGraphics();
            System.out.println("shaan2");
            Font font = new Font("Georgia", Font.BOLD, 18);
            g2d.setFont(font);
            System.out.println("shaan3");
            RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            System.out.println("shaan4");
            rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHints(rh);
            System.out.println("shaan5");
            GradientPaint gp = new GradientPaint(0, 0, Color.red, 0, height / 2, Color.black, true);
            g2d.setPaint(gp);
            g2d.fillRect(0, 0, width, height);
            g2d.setColor(new Color(255, 153, 0));
            System.out.println("shaan6");
            String captcha = String.copyValueOf(s3);
            System.out.println("shaan7");
            int x = 0;
            int y = 0;
            for (int i = 0; i < s3.length; i++) {
                x += 10 + (Math.abs(r.nextInt()) % 15);
                y = 20 + Math.abs(r.nextInt()) % 20;
                g2d.drawChars(s3, i, 1, x, y);
            }
            g2d.dispose();
            System.out.println("shaan8");
            System.out.println("shaan9");

            //Sending Image in output
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "png", baos);
            byte[] imageData = baos.toByteArray();
            System.out.println("shaan10" + captcha);
            request.getSession(true).setAttribute("captcha", captcha);
            System.out.println("shaan11");
            baos.flush();
            baos.close();
            System.out.println("The imageData is :" + imageData);

            return Response.ok(imageData, "image/png").build();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("In Error Catch block");
            e.printStackTrace();
            return Response.status(Status.BAD_REQUEST).build();
        }
    }
}

Then you can use the image like this:

<!DOCTYPE html>
<html>
    <body>
        <h1>Hello World!</h1>
        <img id="captchaImage" alt="muh" src="/YOUR_REST_PATH/reCaptchaImg"/>
    </body>
</html>