67

I am trying to crop/resize user profile images using the jQuery plugin crop.js which sends user images as Base64 via Ajax to my controller:

$.ajax({
        type: "post",
        dataType: "json",
        url: "${g.createLink(controller: 'personalDetail', action:'uploadUserImage')}",
        data: { avatar: canvas.toDataURL() }
        });

But I'm unable to decode this Base64 string to an image:

'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAgAEl...=='

How can I save the Base64 string as an image on my server?

1
  • 1
    You can use decodeBase64() on the encoded string iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAgAEl directly to get the byte array and then create the file as shown in answers. Commented Jun 1, 2014 at 13:58

9 Answers 9

103

In the server, do something like this:

Suppose

String data = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAgAEl...=='

Then:

String base64Image = data.split(",")[1];
byte[] imageBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(base64Image);

Then you can do whatever you like with the bytes like:

BufferedImage img = ImageIO.read(new ByteArrayInputStream(imageBytes));
Sign up to request clarification or add additional context in comments.

1 Comment

This "javax.xml.bind.DatatypeConverter.parseBase64Binary" better than use ".getBytes()" method from a String
77

This assumes a few things, that you know what the output file name will be and that your data comes as a string. I'm sure you can modify the following to meet your needs:

// Needed Imports
import java.io.ByteArrayInputStream;
import sun.misc.BASE64Decoder;


def sourceData = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAgAEl...==';

// tokenize the data
def parts = sourceData.tokenize(",");
def imageString = parts[1];

// create a buffered image
BufferedImage image = null;
byte[] imageByte;

BASE64Decoder decoder = new BASE64Decoder();
imageByte = decoder.decodeBuffer(imageString);
ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
image = ImageIO.read(bis);
bis.close();

// write the image to a file
File outputfile = new File("image.png");
ImageIO.write(image, "png", outputfile);

Please note, this is just an example of what parts are involved. I haven't optimized this code at all and it's written off the top of my head.

6 Comments

@Lucky Groovy doesn't require semicolons at the end of lines.
If you are planning to use JDK > 8 then this code will not work as Base64Decoder is not accessible in JDK 8. I prefer to use javax.xml.bind.DatatypeConverter over Base64Decoder or any class from sun.*** package.
The ImageIO.write() would compress the image by default,the compressed image has the smaller size,but looks strange sometimes. I used the BufferedOutputStream to save the byte array data,this would keep the original image size.
@Ayano how do I do that?
@styl3r I had write the full code of that below this question. my answer
|
31

ImageIO.write() will compress the image by default - the compressed image has a smaller size but looks strange sometimes. I use BufferedOutputStream to save the byte array data - this will keep the original image size.

Here is the code:

import javax.xml.bind.DatatypeConverter;
import java.io.*;

public class ImageTest {
    public static void main(String[] args) {
        String base64String = "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAHkAAAB5C...";
        String[] strings = base64String.split(",");
        String extension;
        switch (strings[0]) {//check image's extension
            case "data:image/jpeg;base64":
                extension = "jpeg";
                break;
            case "data:image/png;base64":
                extension = "png";
                break;
            default://should write cases for more images types
                extension = "jpg";
                break;
        }
        //convert base64 string to binary data
        byte[] data = DatatypeConverter.parseBase64Binary(strings[1]);
        String path = "C:\\Users\\Ene\\Desktop\\test_image." + extension;
        File file = new File(path);
        try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file))) {
            outputStream.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Comments

9

Simplicity is:

import java.util.Base64;

To decode:

byte[] image = Base64.getDecoder().decode(base64string);

To encode:

String text = Base64.getEncoder().encodeToString(imageData);

1 Comment

for this, min OS is Android O.
5

Server side encoding files/Images to base64String ready for client side consumption

public Optional<String> InputStreamToBase64(Optional<InputStream> inputStream) throws IOException{
    if (inputStream.isPresent()) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        FileCopyUtils.copy(inputStream.get(), output);
        //TODO retrieve content type from file, & replace png below with it
        return Optional.ofNullable("data:image/png;base64," + DatatypeConverter.printBase64Binary(output.toByteArray()));
    }

    return Optional.empty();
}

Server side base64 Image/File decoder

public Optional<InputStream> Base64InputStream(Optional<String> base64String)throws IOException {
    if (base64String.isPresent()) {
        return Optional.ofNullable(new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(base64String.get())));
    }

    return Optional.empty();
}

Comments

4
  public Optional<String> InputStreamToBase64(Optional<InputStream> inputStream) throws IOException{
    if (inputStream.isPresent()) {
        ByteArrayOutputStream outpString base64Image = data.split(",")[1];
byte[] imageBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(base64Image);

Then you can do whatever you like with the bytes like:

BufferedImage img = ImageIO.read(new ByteArrayInputStream(imageBytes));ut = new ByteArrayOutputStream();
        FileCopyUtils.copy(inputStream.get(), output);
        //TODO retrieve content type from file, & replace png below with it
        return Optional.ofNullable("data:image/png;base64," + DatatypeConverter.printBase64Binary(output.toByteArray()));
    }

    return Optional.empty();

Comments

2

Hi This is my solution

Javascript code

var base64before = document.querySelector('img').src;
var base64 = base64before.replace(/^data:image\/(png|jpg);base64,/, "");
var httpPost = new XMLHttpRequest();
var path = "your url";
var data = JSON.stringify(base64);

httpPost.open("POST", path, false);
// Set the content type of the request to json since that's what's being sent
httpPost.setRequestHeader('Content-Type', 'application/json');
httpPost.send(data);

This is my Java code.

public void saveImage(InputStream imageStream){
InputStream inStream = imageStream;

try {
    String dataString = convertStreamToString(inStream);

    byte[] imageBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(dataString);
    BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));
    // write the image to a file
    File outputfile = new File("/Users/paul/Desktop/testkey/myImage.png");
    ImageIO.write(image, "png", outputfile);

    }catch(Exception e) {
        System.out.println(e.getStackTrace());
    }
}


static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}

Comments

0

This is Ayano's excellent answer, but in Clojure:

(:import (java.awt.image BufferedImage)
         (javax.xml.bind DatatypeConverter)
         (java.io File BufferedOutputStream FileOutputStream))

(defn write-svg-encountered-image [svg-img-data base-filename]
  (let [[meta img-data] (str/split svg-img-data #",")
        extension (case meta
                    "data:image/jpeg;base64" ".jpeg"
                    "data:image/png;base64" ".png"
                    (throw (Error. (format "Unrecognised image metadata in SVG:" meta))))
        path (str base-filename extension)
        file (File. path)
        data-bytes (DatatypeConverter/parseBase64Binary img-data)
        os (BufferedOutputStream. (FileOutputStream. file))]
      (.write os data-bytes)))

Comments

-1

To Convert all file types

 String[] strings = expense.getAttchBase64().split(",");
                String extension;
                switch (strings[0]) {//check image's extension
                    case "data:image/jpeg;base64":
                        extension = "jpeg";
                        break;
                    case "data:image/png;base64":
                        extension = "png";
                        break;
                    case "data:application/pdf;base64":
                        extension = "pdf";
                        break;
                    case "data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64":
                        extension = "docx";
                        break;
                    default://should write cases for more images types
                        extension = "jpg";
                        break;
                }
                //convert base64 string to binary data
                byte[] data = DatatypeConverter.parseBase64Binary(strings[1]);
                String fileName = UUID.randomUUID().toString();
                String path = "C:\\floridatrading\\" + fileName + "." + extension;
                File file = new File(path);
                try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file))) {
                    outputStream.write(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }

if you need to add any new type just add It in switch .

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.