Javascript - get extension from base64 image
Asked Answered
M

10

62

I have a base64 encoded image returned from a service and it looks like this:

/9j/4AAQSkZJRgABAQEASABIAAD/4Yp2aHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA0LjEtYzAzNiA0Ni4yNzcwOTIsIEZyaSBGZWIgMjMgMjAwNyAxNDoxNjoxOCAgICAgICAgIj4KICAgPHJkZjpSREYgeG1.... etc

How can i detect / check the image extension?

Mixie answered 11/1, 2015 at 11:47 Comment(3)
this is the image code or image picName/url+picName in base64?Mckeown
ok, is the image code, I can obly get this: ÿØÿà JFIF H H ÿáŠvhttp://ns.adobe.com/xap/1.0/ <?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.1-c036 46.277092, Fri Feb 23 2007 14:16:18 "> <rdf:RDF áµMckeown
this is the base64 of the image content, you can get the same encoding an image on this site for example base64-image.deMixie
H
15

For a String (which you can parse out of an image) you can do this:

// Create Base64 Object
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}

// Define the string, also meaning that you need to know the file extension
var encoded = "Base64 encoded image returned from your service";

// Decode the string
var decoded = Base64.decode(encoded);
console.log(decoded);

// if the file extension is unknown
var extension = undefined;
// do something like this
var lowerCase = decoded.toLowerCase();
if (lowerCase.indexOf("png") !== -1) extension = "png"
else if (lowerCase.indexOf("jpg") !== -1 || lowerCase.indexOf("jpeg") !== -1)
    extension = "jpg"
else extension = "tiff";

// and then to display the image
var img = document.createElement("img");
img.src = decoded;

// alternatively, you can do this
img.src = "data:image/" + extension + ";base64," + encoded;

For completion's sake here's the source and I hope this helps!

Haematogenesis answered 11/1, 2015 at 13:16 Comment(6)
hi, thank you but i can't understand how to return the original image extensionMixie
@sbaaaang If you have decoded your payload, i.e. have decoded the Base64 String that the server returned, you have an image like any other. The only difference is, is that you only have the data in your image. In other words the image isn't stored locally, only programmatically.Haematogenesis
yes but how do i get then the decoded file extension? :DMixie
@sbaaaang I have updated my answer. I admit it is a little hacky, but it's the only way to get the file extension with the information the client has.Haematogenesis
Why do you define Base64 object, when there are atob and btoa functions? developer.mozilla.org/en-US/docs/Web/API/WindowBase64/…Caltrop
this didn't work for me. I ended up having this sort of gibberish on the decoded string: "IDATx^흫r鍆P䒲⊖漍&٠೿R+^ú>Ϙ幧�헿 @䂿┳S4" after decoding my base64 image:"iVBORw0KGgoAAAANSUhEUgAAAfIAAAHyCA..." using the method aboveObstruct
D
123

A bit late but it seem the question was misunderstood. He just only had the base64 content of the image, not the full data URI.

I wrote here for anyone who encounters with this quest, you can read the first character of content content.charAt(0). By base64 image content if the first char is:

'/' : jpg

'i' : png

'R' : gif

'U' : webp

So for your case, it is 'jpg'.

Draft answered 1/5, 2018 at 4:34 Comment(6)
I came here looking for this answer. For completeness, U is for webpFrater
While this should be also true for .pdf that has the base64 starting with J, this is not always true on other image types, as I tested this on TIF files and they have base64 starting with i and T.Eccrinology
Adding one more option 'P' : SVGInstruct
What if I wanted to check the videos as well?Impasse
What is the character for TIF?Heman
'U' is also for .aviWithers
S
40

Was just tweaking with the string. May be this could help.

base64Data.substring("data:image/".length, base64Data.indexOf(";base64"))
Skipp answered 20/11, 2016 at 19:38 Comment(1)
this is useful in backend operations where image come in request bodyHuttan
H
34

You could also do it with a function chain.

const type = base64Data.split(';')[0].split('/')[1];
Hostelry answered 1/6, 2017 at 1:9 Comment(0)
H
15

For a String (which you can parse out of an image) you can do this:

// Create Base64 Object
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}

// Define the string, also meaning that you need to know the file extension
var encoded = "Base64 encoded image returned from your service";

// Decode the string
var decoded = Base64.decode(encoded);
console.log(decoded);

// if the file extension is unknown
var extension = undefined;
// do something like this
var lowerCase = decoded.toLowerCase();
if (lowerCase.indexOf("png") !== -1) extension = "png"
else if (lowerCase.indexOf("jpg") !== -1 || lowerCase.indexOf("jpeg") !== -1)
    extension = "jpg"
else extension = "tiff";

// and then to display the image
var img = document.createElement("img");
img.src = decoded;

// alternatively, you can do this
img.src = "data:image/" + extension + ";base64," + encoded;

For completion's sake here's the source and I hope this helps!

Haematogenesis answered 11/1, 2015 at 13:16 Comment(6)
hi, thank you but i can't understand how to return the original image extensionMixie
@sbaaaang If you have decoded your payload, i.e. have decoded the Base64 String that the server returned, you have an image like any other. The only difference is, is that you only have the data in your image. In other words the image isn't stored locally, only programmatically.Haematogenesis
yes but how do i get then the decoded file extension? :DMixie
@sbaaaang I have updated my answer. I admit it is a little hacky, but it's the only way to get the file extension with the information the client has.Haematogenesis
Why do you define Base64 object, when there are atob and btoa functions? developer.mozilla.org/en-US/docs/Web/API/WindowBase64/…Caltrop
this didn't work for me. I ended up having this sort of gibberish on the decoded string: "IDATx^흫r鍆P䒲⊖漍&٠೿R+^ú>Ϙ幧�헿 @䂿┳S4" after decoding my base64 image:"iVBORw0KGgoAAAANSUhEUgAAAfIAAAHyCA..." using the method aboveObstruct
D
12

A bit late, but you can do it using the file-type module in Node.JS:

npm install file-type

var fileType = require("file-type");

var base64string = "/9j/4AAQSkZJRgABAQEASABIAAD/4Yp2aHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA0LjEtYzAzNiA0Ni4yNzcwOTIsIEZyaSBGZWIgMjMgMjAwNyAxNDoxNjoxOCAgICAgICAgIj4KICAgPHJkZjpSREYgeG1";
var base64string_buffer = Buffer.from(base64string, "base64");

(async ()=>{

    var result = await fileType.fromBuffer(base64string_buffer);
    console.log(result);
    //Returns  { ext: 'jpg', mime: 'image/jpeg' }

})();

According to file-type's npm page, it works on getting the magic number which can be found in the returned buffer item. For example, a jpeg starts with ff d8, a pdf with 25 50 44 46, etc.

For reference, here's a snippet from base64string_buffer.toString('hex').match(/../g).join(' '):

ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 48 00 48 00 00 ff e1 8a 76 68 74 74 70 .....

Demanding answered 23/11, 2020 at 18:50 Comment(0)
B
8

This one will work for any extension type: pdf, mp3, png, ....

base64.substring(base64.indexOf('/') + 1, base64.indexOf(';base64'));

Bellyband answered 10/8, 2018 at 15:18 Comment(0)
M
7

use my js function ! it can check JPG,PNG,BMP and so on.

/**
 * @author PiaoZhenJia
 */
function base64FileHeaderMapper(fileBase64) {

    let fileHeader = new Map();

    //get the first 3 char of base64
    fileHeader.set("/9j", "JPG")
    fileHeader.set("iVB", "PNG")
    fileHeader.set("Qk0", "BMP")
    fileHeader.set("SUk", "TIFF")
    fileHeader.set("JVB", "PDF")
    fileHeader.set("UEs", "OFD")

    let res = ""

    fileHeader.forEach((v, k) => {
        if (k == fileBase64.substr(0, 3)) {
            res = v
        }
    })

    //if file is not supported
    if (res == "") {
        res = "unknown file"
    }

    //return map value
    return res;
}
Marrero answered 14/10, 2021 at 12:17 Comment(1)
Mine starts with JTV lolMidsummer
M
6

By the way you provided invalid Base64 string. correct syntax of base64 encoded image string is like this

"data:image/png;base64,abcdefghijklmnopqrstuvwxyz0123456789......"

You can parse that string and can get the information out of it

const base64str = {profilepic:"data:image/png;base64,abcdefghijklmnopqrstuvwxyz0123456789"};
let mimeType = base64str.profilepic.match(/[^:]\w+\/[\w-+\d.]+(?=;|,)/)[0];

You can see demo here

and if you want to get only extensions you can use following code to get that one. using regex to parse base64 string and get the extension.

const body2 = {profilepic:"data:image/png;base64,abcdefghijklmnopqrstuvwxyz0123456789"};
let mimeType2 = body2.profilepic.match(/[^:/]\w+(?=;|,)/)[0];

check online working Demo here

Monarda answered 2/10, 2019 at 11:20 Comment(1)
Simple not complicated and it works, how many times would you have a string like the OPs in a real production enviroment. I just needed the extention i used your option two.Parson
M
1

This one Worked for me perfectly. It will return file type in format 'image/png'

    function base64MimeType(encoded) {
      var result = null;
    
      if (typeof encoded !== 'string') {
        return result;
      }
    
      var mime = encoded.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/);
    
      if (mime && mime.length) {
        result = mime[1];
      }
    
      return result;
    }
Mishmash answered 27/7, 2020 at 11:46 Comment(0)
H
0

The above function always returns null

Havoc answered 12/4, 2023 at 6:25 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Thierry

© 2022 - 2024 — McMap. All rights reserved.