I am trying to crop/resize user profile image using jquery plugin namely crop.js which sends user image as base64 via ajax to my controller as
$.ajax({ type: "post", dataType: "json", url: "${g.createLink(controller: 'personalDetail', action:'uploadUserImage')}", data: { avatar: canvas.toDataURL() } }); but I unable to decode this base64
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAgAEl...==' string as Image,Can you guys guide me how can I save my base64 string as image on my server?.
18 Answers
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)); 1This 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.
6ImageIO.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(); } } } Simplicity is:
import java.util.Base64; To decode:
byte[] image = Base64.getDecoder().decode(base64string); To encode:
String text = Base64.getEncoder().encodeToString(imageData); 0Server 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(); } 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(); 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() : ""; } 0This 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)))