Reputation: 89
I want to check HTML img src is in base64 encoded format or not in my java spring backend. if it is Base64 encoded then I will just decode image and save to my server if it is not I will download firstly based on image URL path then save to my server. I've built a downloading image and decoding image functions. But can't resolve the base64 check. I tried to use try catch checking statement but I do not need catching error if it is not base64. P.S I am using java.util.Base64
public boolean isBase64(String path) {
try {
Base64.getDecoder().decode(path);
} catch(IllegalArgumentException e) {
}
}
Upvotes: 2
Views: 12049
Reputation: 1
test Base64.getDecoder().decode(input) return true always... :-( try this (works for me):
private boolean testStringIsBase64(String input) {
boolean result = false;
String test;
try {
test = convertStringFromBase64(input);
if (input.equals(convertStringToBase64(test))) {
result = true;
}
}
catch (Exception ex) {
result = false;
}
return result;
}
private String convertStringToBase64(String input) {
return Base64.getEncoder().encodeToString(input.getBytes());
}
private String convertStringFromBase64(String input) {
return new String(Base64.getDecoder().decode(input));
}
whenever you try encode and back to decode and strings are same, input is Base64
R.
Upvotes: 0
Reputation: 869
I'm still not sure whether you're looking at URL's or want to inspect the data.
For the latter, you could do something like this...
/*
* Some typical Image-File Signatures (starting @ byte 0)
*/
private static final byte[] JPG_1 = new byte[] {-1, -40, -1, -37};
private static final byte[] JPG_2 = new byte[] {-1, -40, -1, -18};
private static final byte[] PNG = new byte[] {-119, 80, 78, 71, 13, 10, 26, 10};
public static boolean isMime(final InputStream ist) {
/*
* The number of bytes of Mime-encoded Data you want to read.
* (4 * 19 = 76, which is MIMELINEMAX from Base64$Encoder)
*/
final int mimeBlockLength = 4; // <- MUST be 4!
final int mimeBlockCount = 19; // <- your choice
final int mimeBufferLength = mimeBlockCount * mimeBlockLength;
final byte[] bar = new byte[mimeBufferLength];
try (final BufferedInputStream bis = new BufferedInputStream(ist, mimeBufferLength))
{
/*
* We expect at least one complete Mime-encoded buffer...
*/
if (bis.read(bar) != mimeBufferLength) {
return false;
}
/*
* Use a Java 9 feature to compare Signatures...
*/
if (Arrays.equals(bar, 0, JPG_1.length, JPG_1, 0, JPG_1.length)
|| Arrays.equals(bar, 0, JPG_2.length, JPG_2, 0, JPG_2.length)
|| Arrays.equals(bar, 0, PNG .length, PNG , 0, PNG .length)) {
return true;
} else {
return false;
}
} catch (final IOException e) {
return false;
}
}
Upvotes: 0
Reputation: 862
If you receive the exact value by <img src="..." />
attribute then it should have Data URL format
The simple regexp could determine whether the URL is Data or regular. In java it can look like
private static final Pattern DATA_URL_PATTERN = Pattern.compile("^data:image/(.+?);base64,\\s*", Pattern.CASE_INSENSITIVE);
static void handleImgSrc(String path) {
if (path.startsWith("data:")) {
final Matcher m = DATA_URL_PATTERN.matcher(path);
if (m.find()) {
String imageType = m.group(1);
String base64 = path.substring(m.end());
// decodeImage(imageType, base64);
} else {
// some logging
}
} else {
// downloadImage(path);
}
}
Upvotes: 1
Reputation: 42585
Theoretically you can't decide if some string is base64 decoded or not, because by chance any regular string may be base64 decodable.
In reality however for longer data the chance is low that it is base64 decodeable but not a base64 encoded data.
In general I don't see a problem in your approach, your method just need some small improvements:
public boolean isBase64(String path) {
try {
Base64.getDecoder().decode(path);
return true;
} catch(IllegalArgumentException e) {
return false;
}
}
In my opinion this approach is very inefficient because if the data is base64 decodable I assume you want the base64 decoded data. Therefore in such a case you are performing the base64 decoding twice (one time for checking isBase64
and one time for the actual encoding). Therefore I would use something like this:
public byte[] tryDecodeBase64(String path) {
try {
return Base64.getDecoder().decode(path);
} catch(IllegalArgumentException e) {
return null;
}
}
Upvotes: 1