jdk1.8 Base64Util Illegal base64 character

Keywords: Java encoding JDK Apache

Encoding and transcoding of jdk1.8 base64

Practical scenario

Recently, there is a need to download the image to the local according to its url, and the client cannot access the url and can only receive Base64 image code. Therefore, it is decided to use the base64 provided by jdk for encoding and transcoding storage.

Episode

Two tool classes are used: ImageUtil and Base64Util. ImageUtil is used for actual operation. Base64Util is used for unified encoding format.

Because the built-in Base64 of jdk1.7 and jdk1.8 does not conform to the RFC protocol, jdk1.7 is implemented according to RFC1521, and jdk1.8 is implemented according to rfc4648 and rfc2045. The details can be found in the class annotation. Due to different protocols, java.lang.IllegalArgumentException: Illegal base64 character a exception may be thrown when jdk1.8 decodes the data encoded by jdk1.7. Therefore, special attention should be paid to keep the consistency of decoding and encoding.

The coding result of jdk7 includes line breaking;
The encoding result of jdk8 does not contain line breaking;
jdk8 is unable to decode the encoding result including line breaking;

Now that we know the cause of the above exceptions, it's easy to find a solution.

  1. Use the org.apache.commons.codec.binary.Base64 class in the apache common package to encode and decode;
  2. Remove line breaks after encoding or before decoding;
  3. The same jdk version is used for encoding and decoding;

Attach code

ImageUtils

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

public class ImageUtils {

    /**
     * base64 Address of document transfer
     *
     * @param filePath
     * @param base64
     * @param fileName
     */
    public static void base64ToImg(String filePath, String base64, String fileName) {
        File file = null;
        //Create file directory
        File dir = new File(filePath);
        if (!dir.exists() && !dir.isDirectory()) {
            dir.mkdirs();
        }
        BufferedOutputStream bos = null;
        java.io.FileOutputStream fos = null;
        try {
            byte[] bytes = Base64Util.decode(base64);
            file = new File(filePath + fileName);
            fos = new java.io.FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Get base64 through Toolkit
     *
     * @param url
     * @return
     * @author caoting
     * @date 2018 November 21, 2010
     */
    public static String getBase64ByImgUrl(String url) {
        String suffix = url.substring(url.lastIndexOf(".") + 1);
        try {
            URL urls = new URL(url);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            Image image = Toolkit.getDefaultToolkit().getImage(urls);
            BufferedImage biOut = toBufferedImage(image);
            ImageIO.write(biOut, suffix, baos);
            String base64Str = Base64Util.encode(baos.toByteArray());
            return base64Str;
        } catch (Exception e) {
            return "";
        }

    }

    public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }
        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            int transparency = Transparency.OPAQUE;
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }
        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }
        // Copy image to buffered image
        Graphics g = bimage.createGraphics();
        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return bimage;
    }

    /**
     * Get base64 by downloading binary stream
     *
     * @param imgUrl Picture url
     * @return Returns the string of picture base64
     */
    public static String image2Base64(String imgUrl) {

        URL url = null;
        InputStream is = null;
        ByteArrayOutputStream outStream = null;

        HttpURLConnection httpUrl = null;
        try {

            url = new URL(imgUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();

            httpUrl.getInputStream();
            is = httpUrl.getInputStream();
            outStream = new ByteArrayOutputStream();

            // Create a Buffer string
            byte[] buffer = new byte[1024];
            // The length of each read string. If it is - 1, it means that all the reads are completed
            int len = 0;
            // Use an input stream to read data from the buffer
            while ((len = is.read(buffer)) != -1) {
                // Use the output stream to write data into the buffer. The middle parameter represents the position from which to start reading, and len represents the length of reading
                outStream.write(buffer, 0, len);
            }
            // Encoding byte array Base64
            return Base64Util.encode(outStream.toByteArray());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outStream != null) {
                try {
                    outStream.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (httpUrl != null) {
                httpUrl.disconnect();
            }
        }
        return imgUrl;
    }
}

Base64Util


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.stream.FileImageInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Base64Util{
    /**
     * String to picture
     * @param base64Str
     * @return
     */
    public static byte[] decode(String base64Str){
        byte[] b = null;
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            b = decoder.decodeBuffer(replaceEnter(base64Str));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return b;
    }

    /**
     * Picture to string
     * @param image
     * @return
     */
    public static String encode(byte[] image){
        BASE64Encoder decoder = new BASE64Encoder();
        return replaceEnter(decoder.encode(image));
    }

    public static String encode(String uri){
        BASE64Encoder encoder = new BASE64Encoder();
        return replaceEnter(encoder.encode(uri.getBytes()));
    }

    /**
     *
     * @path    Picture path
     * @return
     */

    public static byte[] imageTobyte(String path){
        byte[] data = null;
        FileImageInputStream input = null;
        try {
            input = new FileImageInputStream(new File(path));
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            int numBytesRead = 0;
            while((numBytesRead = input.read(buf)) != -1){
                output.write(buf, 0, numBytesRead);
            }
            data = output.toByteArray();
            output.close();
            input.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return data;
    }

    public static String replaceEnter(String str){
        String reg ="[\n-\r]";
        Pattern p = Pattern.compile(reg);
        Matcher m = p.matcher(str);
        return m.replaceAll("");
    }
}

Posted by justspiffy on Fri, 06 Dec 2019 05:35:25 -0800