How to convert an Image to base64 string in java? [duplicate] - java

This question already has answers here:
Encoding as Base64 in Java
(19 answers)
Closed 6 years ago.
It may be a duplicate but i am facing some problem to convert the image into Base64 for sending it for Http Post. I have tried this code but it gave me wrong encoded string.
public static void main(String[] args) {
File f = new File("C:/Users/SETU BASAK/Desktop/a.jpg");
String encodstring = encodeFileToBase64Binary(f);
System.out.println(encodstring);
}
private static String encodeFileToBase64Binary(File file){
String encodedfile = null;
try {
FileInputStream fileInputStreamReader = new FileInputStream(file);
byte[] bytes = new byte[(int)file.length()];
fileInputStreamReader.read(bytes);
encodedfile = Base64.encodeBase64(bytes).toString();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return encodedfile;
}
Output: [B#677327b6
But i converted this same image into Base64 in many online encoders and they all gave the correct big Base64 string.
Edit: How is it a duplicate?? The link which is duplicate of mine doesn't give me solution of converting the string what i wanted.
What am i missing here??

The problem is that you are returning the toString() of the call to Base64.encodeBase64(bytes) which returns a byte array. So what you get in the end is the default string representation of a byte array, which corresponds to the output you get.
Instead, you should do:
encodedfile = new String(Base64.encodeBase64(bytes), "UTF-8");

I think you might want:
String encodedFile = Base64.getEncoder().encodeToString(bytes);

this did it for me. you can vary the options for the output format to Base64.Default whatsoever.
// encode base64 from image
ByteArrayOutputStream baos = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
encodedString = Base64.encodeToString(b, Base64.URL_SAFE | Base64.NO_WRAP);

Related

Java - Obtain PDF from URL and return BASE64 string

I have the following task to obtain a PDF from URL and return a BASE64 string.
What I have currently (sorry I am not a Java Expert):
public String readPDFSOAP(String var, Container container) throws StreamTransformationException{
try {
//get the url page from the arguments array
URL url = new URL("URLPDF");
try {
//get input Stream from URL
InputStream in = new BufferedInputStream(url.openStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[131072];
int n = 0;
while (-1 != (n = in.read(buf))) {
out.write(buf, 0, n);
}
out.close();
in.close();
byte[] response = out.toByteArray();
String string = new String(response);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}return String;}
But the string can't be returned.
Any help is appreciated.
Thanks,
Julian
Your code is all kinds of wrong. For starters, use the Base64 class to handle encoding your byte array. And no need to assign it to a variable, just return it.
return Base64.getEncoder().encodeToString(response)
and on your last line, outside of your try/catch block, just throw an exception. If you get there then you weren't able to properly retrieve and encoded the response, so no need to return a value. You're in an error condition.
Use java.util.Base64.
PDFs can be pretty large. Instead of reading it into memory, encode the InputStream directly:
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (InputStream in = new BufferedInputStream(url.openStream())) {
in.transferTo(Base64.getEncoder().wrap(out));
}
String base64 = out.toString(StandardCharsets.US_ASCII);
The Base64 encoded version is even larger than the original file. I don’t know what you plan to do with the encoded version, but if you’re planning to write it somewhere, you want to avoid keeping any version of the file—original or encoded—in memory. You can do that by having your method accept an OutputStream as an argument:
public void readPDFSOAP(OutputStream destination,
String var,
Container container)
throws StreamTransformationException,
IOException {
URL url = new URL("https://example.com/doc.pdf");
try (InputStream in = new BufferedInputStream(url.openStream())) {
in.transferTo(Base64.getEncoder().wrap(destination));
}
}
Update:
Since you have said you cannot use a try-with-resources statement:
A try-with-resources statement is just a convenient way to guarantee an InputStream (or other closeable resource) is closed. This:
try (InputStream in = new BufferedInputStream(url.openStream())) {
// code that uses 'in'
}
is (nearly) equivalent to this:
InputStream in = null;
try {
in = new BufferedInputStream(url.openStream());
// code that uses 'in'
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// Suppress
}
}
}

Python generated zlib + base64 text getting incorrect header check exception in Java

I am required to write a consumer in Java from Kafka streams, publisher app is written by a third party in python. When I use base64 decoding and then zlip uncompress in java, I get an incorrect header check exception.
My Task is: Convert this compressed base64 + zlib data into a text file that is readable.
Publisher's code in python:
# read in the file content
inputf=open(file, 'rb')
input=inputf.read()
inputf.close()
# using zlib.compress(s) method
compressed = zlib.compress(input)
# encoding with base64 encoding
encoding_type='base64'
enc_data=encode(compressed,encoding_type)
enc_data_utf8=enc_data.decode("utf-8")
# enc_data=enc_data_no_no_newline ####[0:86000] # trim
event_etl_event[filename+"_content"]=enc_data_utf8
event_etl_event[filename+"_compressed_format"]="zlib+uuencode"
enter code here
Consumer Code in java
public void processData(){
inputStr = event.getEventEtlEvent().getAllProblemsTxtContent();
System.out.println("Before Base64 decoding: \n" + inputStr);
Path path0 = Paths.get("AllProblems_Before_base64_decoding.txt");
Files.write(path0, inputStr.getBytes());
Base64 base64 = new Base64();
String decodedString = new String(base64.decode(inputStr.getBytes()));
System.out.println("After Base64 decode: \n" + decodedString);
Path path1 = Paths.get("AllProblems_After_base64_decoding.txt");
Files.write(path1, decodedString.getBytes());
System.out.println("now zlib 64 decodingString .........\n\n\n");
byte[] output = ZLibUtils.decompress(decodedString.getBytes());
System.out.println("After Zlib Decompress: "+ output);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} /*catch (InvalidDataException e) {
e.printStackTrace();
} catch (DataFormatException e) {
e.printStackTrace();
}*/catch (Exception e) {
e.printStackTrace();
}
ZLibUtils.java
public static byte[] decompress(byte[] data) throws DataFormatException {
byte[] output = new byte[0];
Inflater decompresser = new Inflater();
decompresser.reset();
decompresser.setInput(data);
ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);
// try {
byte[] buf = new byte[data.length];
byte[] a = new byte[data.length];
while (!decompresser.finished()) {
int i = decompresser.inflate(buf);
o.write(buf, 0, i);
}
output = o.toByteArray();
/* } catch (Exception e) {
output = data;
e.printStackTrace();
//FIXME: in later code
System.exit(0);
} finally {
try {
o.close();
} catch (IOException e) {
e.printStackTrace();
}
} */
decompresser.end();
return output;
}
Now when I run my program, i get the following exception:
java.util.zip.DataFormatException: incorrect header check
at java.util.zip.Inflater.inflateBytes(Native Method)
at java.util.zip.Inflater.inflate(Inflater.java:259)
at java.util.zip.Inflater.inflate(Inflater.java:280)
at com.exmple.util.ZLibUtils.decompress(ZLibUtils.java:84
)
Looking forward to hearing from you soon.
The problem is that you convert the base64 decoded data from a byte array into a string and back into a byte array. For most encodings this is not a no-op. That means, for most encodings and most byte arrays,
byte[] decoded = { (byte) 0x9b, 1, 2, 3 };
String decodedString = new String(decoded);
byte[] processed = decodedString.getBytes();
the contents of processed will be different from the contents of decoded.
The solution is to not treat the base64 decoded data as string and instead of that work with the byte data directly:
Base64 base64 = new Base64();
byte[] decoded = base64.decode(inputStr.getBytes());
Path path1 = Paths.get("AllProblems_After_base64_decoding.txt");
Files.write(path1, decoded);
System.out.println("now zlib 64 decodingString .........\n\n\n");
byte[] output = ZLibUtils.decompress(decoded);

Why the result is different for twice common-codec md5

when I use apache common-codec md5Hex to get the inputstream's md5 result,but get the different result for twice. the example code is below :
public static void main(String[] args) {
String data = "D:\\test.jpg";
File file = new File(data);
InputStream is = null;
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String digest = null, digest2 = null;
try {
System.out.println(is.hashCode());
digest = DigestUtils.md5Hex(is);
System.out.println(is.hashCode());
digest2 = DigestUtils.md5Hex(is);
System.out.println(is.hashCode());
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Digest = " + digest);
System.out.println("Digest2 = " + digest2);
}
and the result is:
1888654590
1888654590
1888654590
Digest = 5cc6c20f0b3aa9b44fe952da20cc928e
Digest2 = d41d8cd98f00b204e9800998ecf8427e
Thank you for answer!
d41d8cd98f00b204e9800998ecf8427e is the md5 hash of the empty string ("").
That is because is is a stream, meaning that once you've read it (in DigestUtils.md5Hex(is)), the "cursor" is at the end of the stream, where there is no more data to read, so attempting to read anything will return 0 bytes.
I suggest reading the contents of the stream to a byte[] instead, and hashing that.
For how to get a byte[] from an InputStream, see this question.
The InputStream can be traversed only once. The first call traverses it and returns the MD5 for your input file. When you call md5hex the second time, the InputStream points to the end-of-file, thus the digest2 is the MD5 for empty input.
You cannot move back within InputStream. So invoking twice:
DigestUtils.md5Hex(is);
is not the same. Better read into byte array and use:
public static String md5Hex(byte[] data)

how to convert text file of base64 into xml file(or any other type of file)

I have these Base64 in a text file:
77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxSb290Pg0KICA8SXRl
bXM+DQogICAgPEl0ZW0gTmFtZT0iQ2xhaW1OdW1iZXIiIFZhbHVlPSI0ODY1MTQ4MDQiIC8+DQog
ICAgPEl0ZW0gTmFtZT0iRG9jVHlwZSIgVmFsdWU9IkxpdGlnYXRpb24iIC8+DQogICAgPEl0ZW0g
TmFtZT0iRG9jU3ViVHlwZSIgVmFsdWU9IklOVCBBbnN3ZXJzIiAvPg0KICAgIDxJdGVtIE5hbWU9
IkRvY0RhdGVzIiBWYWx1ZT0iNi8xNC8yMDExIDEyOjAwOjAwIEFNIiAvPg0KICAgIDxJdGVtIE5h
bWU9IkNvbW1lbnRzIiBWYWx1ZT0iUGx0ZiBhbnN3ZXJzIHRvIGludHMgYW5kIHN1bW1hcnkgYnkg
ZGVmZW5zZSBjb3Vuc2VsIiAvPg0KICAgIDxJdGVtIE5hbWU9IlNlY3VyaXR5R3JvdXAiIFZhbHVl
PSJTcGVjIEdlbiIgLz4NCiAgICA8SXRlbSBOYW1lPSJDbGFpbU9mZmljZSIgVmFsdWU9IkFsdCBN
a3RzIE5KIiAvPg0KICAgIDxJdGVtIE5hbWU9IkNsYWltYW50TmFtZSIgVmFsdWU9IkpvYW4gS2Vs
bGV5IiAvPg0KICAgIDxJdGVtIE5hbWU9Ikluc3VyZWROYW1lIiBWYWx1ZT0iQm96dXR0byAmYW1w
OyBBc3NvY2lhdGVzIiAvPg0KICAgIDxJdGVtIE5hbWU9IlByaXZpbGVnZWQiIFZhbHVlPSJObyIg
Lz4NCiAgICA8SXRlbSBOYW1lPSJEaXNwb3NpdGlvbiIgVmFsdWU9IlNlbnQgdG8gRmlsZSIgLz4N
CiAgICA8SXRlbSBOYW1lPSJGZWF0dXJlIiBWYWx1ZT0iIiAvPg0KICAgIDxJdGVtIE5hbWU9IlNl
bnRUbyIgVmFsdWU9IiIgLz4NCiAgICA8SXRlbSBOYW1lPSJGbGFnIiBWYWx1ZT0iMCIgLz4NCiAg
ICA8SXRlbSBOYW1lPSJSZXRhaW5JbWFnZSIgVmFsdWU9Ik5vIiAvPg0KICAgIDxJdGVtIE5hbWU9
IlJldGFpbk9yaWdpbmFsIiBWYWx1ZT0iRG8gTm90IFJldGFpbiIgLz4NCiAgICA8SXRlbSBOYW1l
PSJTb3VyY2UiIFZhbHVlPSJJTkRFWEVEIiAvPg0KICA8L0l0ZW1zPg0KICA8Um91dGU+DQogICAg
PHRvIC8+DQogICAgPGNjIC8+DQogICAgPE5vdGUgLz4NCiAgPC9Sb3V0ZT4NCjwvUm9vdD4=
I need to be able to take those base 64 charecters from the text file and output a new XML File. Currently, the InputStream is not being correctly converted to base 64
public static void main(String[] args) {
try {
File file = new File("C:\\Users\\khurt\\Desktop\\xml.txt");
InputStream myScan = new FileInputStream(file);
byte[] b = new byte[(int)file.length()];
myScan.read(b);
String cowo = myScan.toString();
String decoded = DatatypeConverter.printBase64Binary(b);
String cat = b.toString();
System.out.println(decoded);
byte[] bArray = cat.getBytes();
OutputStream out = new FileOutputStream("C:\\Users\\gdfurt\\Desktop\\cow.xml");
out.write(b);
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I used the System.out.println(decode); to check to see if the charecters matched the ones in the file and they do not. I can't figure out why, I have tried using a scanner and that throws it off more.
Data you have got is Base64 encoded. and you are not decoding it in your code. That is main reason behind other programs cannot read it as XML file.
Another is hidden in your Bytes of data. Start of Byte data is 77u/ which is saying data is BINARY data and becomes problem here.
Use Link to experience decoded data:
http://www.opinionatedgeek.com/dotnet/tools/base64decode/
If you will use 77u/ at start of data you will experience data is BINARY and will get downloaded as file. And if you do not use 77u/ it will show output online only.
Remove first 4 char while processing your data and then you are good to go inside java code only.
EDIT
Please use below code snippet. You are re-encoding byte array. You need to decode it. Also this process needs little bit conversions of String to Byte and vice-versa.
try {
File file = new File("C:\\Users\\ABC\\Desktop\\xml.txt");
InputStream myScan = new FileInputStream(file);
byte[] b = new byte[(int)file.length()];
myScan.read(b);
String cowo = new String(b);
System.out.println( cowo );
String decoded = new String(DatatypeConverter.parseBase64Binary(cowo));
String cat = b.toString();
System.out.println(decoded);
byte[] bArray = cat.getBytes();
OutputStream out = new FileOutputStream("C:\\Users\\ABC\\Desktop\\cow.xml");
out.write(decoded.getBytes());
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Read the bytes:
byte[] b;
try (InputStream in = new FileInputStream(file)) {
b = new byte[(int) file.length()];
in.read(b);
} // Closes in
Which in Java 7 goes easier:
b = Files.readAllBytes(file.toPath());
or immediately with Path i.o. Fiile:
Path path = Paths.get("C:\\Users\\khurt\\Desktop\\xml.txt");
b = Files.readAllBytes(path);
As Base64 only uses ASCII do:
String encoded = new String(b, StandardCharsets.US_ASCII);
Parse Base64 text to byte[]
b = DatatypeConverter.parseBase64Binary(encoded);
If you want the XML as text:
String decoded = new String(b, StandardCharsets.UTF_8);
By the way, the XML starts with "\ufeff" the Unicode BOM character, which is redundand.
Addendum 2021-11-16
Nowadays there is one Base64 class in java SE:
b = Base64.getDecoder().decode(b);
or even (suitable for large files):
b = Base64.getDecoder().decode(Files.newInputStream(path));

Http get/post for encoded String

i have question about sending and getting the encoded data for image. Firstly i have image as Base64 encoded type in String, this string has a value such as below :
...D/2wBDAA0JCgsKCA0LCgsODg0PEyAVExISEyccHhcgLikxMC4pLSwzOko+MzZ...
Now if i decode again and if i use BitmapFactory to accomodate on imageview thats all right the image is ok.
byte[] bytes= stream.toByteArray();
imagestr=Base64.encodeBytes(bytes).toString();
//If i code below it is working
byte[] decode = Base64.decode(imagestr);
decoded = BitmapFactory.decodeByteArray(decode, 0, decode.length);
//If i send to the server and handle it in servlet file
String pic = request.getParameter("p");
byte[] servdec = Base64.decode(pic);
//and if i use the servdec to output a image file file is corrupted.
//I noticed the pic and imagestr are different
//imagestr = **...D/2wBDAA0JCgsKCA0LCgsODg0PEyAVExISEyccHhcgLikxMC4pLSwzOko+MzZ...**
//pic = **...D/2wBDAA0JCgsKCA0LCgsODg0PEyAVExISEyccHhcgLikxMC4pLSwzOko MzZ...**
//pic has no + sign.
I used replaceAll but it is only for this case. It may cause more prob. so is there any solution can you advice thank you for your answers...
Hi, this string is in pic which comes to this function, after this function servlet will handle this !pic has + sign in this function
public String uuidfaceid(String uuid,String faceid, String name,String pic){
URL url = null;
try {
url = new
URL("http://"+Constants.SERVER_NAME+Constants.SERVER_PORT+"/MeetInTouch/UF"+"?
uuid="+uuid+"&faceid="+faceid+"&name="+name+"&pic="+pic);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
URLConnection ucon = null;
try {
ucon = url.openConnection();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
ucon.connect();
} catch (IOException e1) {
e1.printStackTrace();
}
The parameter that "p" that contains the Base64 encoded string has been "url decoded" at some point. All you have to do is encode it again before you try to decode the Base64:
String pic = request.getParameter("p");
pic = URLEncoder.encode(pic, "ISO-8859-1");
byte[] servdec = Base64.decode(pic);

Categories

Resources