Img src path with header params to pass - javascript

I have an img tag in jsp page where the src path requires header parameters to pass to get the image. How can we achieve it?

You can now use fetch() to add your headers and then load the result into an <img>:
const src = 'https://api.mywebsite.com/profiles/123/avatar';
const options = {
headers: {
'Some-Header': '...'
}
};
fetch(src, options)
.then(res => res.blob())
.then(blob => {
imgElement.src = URL.createObjectURL(blob);
});

First, you'll need to make an ajax request that sets the headers. Then, you need to use some HTML5 APIs to convert binary data recieved to base64. Finally, set the image src with the data: protocol and your base64 data.
var oReq = new XMLHttpRequest();
oReq.open("GET", "yourpage.jsp", true);
oReq.setRequestHeader("Your-Header-Here", "Value");
// use multiple setRequestHeader calls to set multiple values
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
var arrayBuffer = oReq.response; // Note: not oReq.responseText
if (arrayBuffer) {
var u8 = new Uint8Array(arrayBuffer);
var b64encoded = btoa(String.fromCharCode.apply(null, u8));
var mimetype="image/png"; // or whatever your image mime type is
document.getElementById("yourimageidhere").src="data:"+mimetype+";base64,"+b64encoded;
}
};
oReq.send(null);
Sources:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
How to convert uint8 Array to base64 Encoded String?

You can't access to the header params with the img tag, you've got two solutions :
Use an Ajax request with the header param and load the image data
<img src="data:image/png;base64,[CODE-OF-THE-IMAHE]">
Use GET parameters with a token to replace the header for this functionality
<img src="controller?token=[TOKEN]">

You can use following ugly inline hack
<img src onerror="fetch('https://picsum.photos/200',{headers: {hello:'World!'}}).then(r=>r.blob()).then(d=> this.src=window.URL.createObjectURL(d));" />

Related

turn image binary data into img tag

When i do a post request to a route i have
/generate/image
i get something like: var file =
����JFIF��C��C��� ��
�����+�}Yϭ�F39M>���������>���;��ˋ��uXʽ�w�ڤx\-[2g��k�S���H���m
[�V?[_W����#��v��}6�[��F�F�%����n�...
in the client i do:
var blob = new Blob([file], {type: 'image/png'});
var reader = new FileReader();
reader.onload = function (e) {
$('#result').attr('src', e.target.result);
};
reader.readAsDataURL(blob);
but i get a corrupt image
what can i do?
EDIT:
if i do
img.src = 'data:image/png;base64,' + btoa(file);
i get:
Uncaught InvalidCharacterError: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
Please don't use base64 and wast bandwidth + CPU
Send the image binary as is and handle them correctly with Ajax.
You should not get the result as a string. set xhr responseType to blob or use fetch's blob method.
fetch("/generate/image").then(res => res.blob())
When you have the blob don't use the file reader to turn it to a url.
Use URL.createObjectURL(blob)
At your backend you can do following:
var fs = require('fs');
fs.readFile(path to image from you file, 'base64', function(err, buf){
/* Here you can send your base64 image data to client. Your base64 data is in buf.
I am using socket. You can just send. Read more about readFile function*/
socket.emit('image upload', { image: true, buffer: buf });
});
As my client receives data from socket, I call a function:
socket.on('image upload', function(data){
displayImage(data);
});
var displayImage = function(data){
var URL = 'data:image/jpg;base64,'+data.buffer;
document.querySelector('#img-id').src = URL;
};
The image will then be showed in img tag.
Hope this works for you.

Get response headers when loading an image from AWS S3

I have images stored on S3 with description stored in metadata, following their recommendation for storing metadata
How can I retrieve the response headers when showing the image directly in the browser? I have tried looking in the onload event on an img element but can't find the headers. I have also tried XMLHttpRequest which gets me the headers in the response but I'm not then able to use the responseText as img src.
Eventually I found this fiddle and got the images via XMLHttpRequest, then set the desc from headers on to the image in a custom attribute:
function(image_path, img){
// Use a native XHR so we can use custom responseType
var xhr = new XMLHttpRequest();
xhr.open("GET", image_path, true);
// Ask for the result as an ArrayBuffer.
xhr.responseType = "arraybuffer";
xhr.onload = function( e ) {
// Obtain a blob: URL for the image data to draw it
var arrayBufferView = new Uint8Array( this.response );
var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } );
var imageUrl = URL.createObjectURL( blob );
img.src = imageUrl;
// Get the description from S3 metadata
var desc = this.getResponseHeader('x-amz-meta-description');
img.setAttribute('data-description', desc);
};
xhr.send();
}
If you need to get response headers before image loading or without image loading, you can use head query.When this query is executed, you will receive only headers, is much more efficient if you need only custom data without a file.
$.ajax({url:imageUrl,type:"HEAD"}).always(function(data,content,xhr){
var desc = xhr.getResponseHeader('x-amz-meta-description');
console.log(desc)
});

retrieving pictures stored as blob in the database and display it in the html

i have a medium blob data type on my database, it is storing pictures with gif,jpg,png,bmp types.
i am retrieving the blob using jsf.
i have read this question -> Using Javascript to Display Blob
but i was confused how he converted his blob to base64.
this is what i have done so far.
var blob;
var base64;
var image;
<ui:repeat value="#{testController.allItems}" var="item">
blob = "#{item.logo}";
base64 = btoa(blob);
image = document.createElement('img');
image.src = 'data:image/png;base64,'+ base64 ;
$('#testDiv').append(image);
</ui:repeat>
the above code just gives me a broken link pictures.
sample blob from inspect element
blob = "[B#2d8f2913";
and the image inside the div
<img src="data:image/png;base64,W0JAMmQ4ZjI5MTM=">
UPDATED my code based on Ian's suggestion
i created a method RenderLogo
public String RenderLogo(byte[] rawLogo) {
String base64String = Base64.encodeBase64URLSafeString(rawLogo);
return base64String;
}
now on my js:
var base64;
var image;
<ui:repeat value="#{testController.allItems}" var="item">
base64= '#{testController.RenderLogo(item.logo)}';
image = document.createElement('img');
image.src = 'data:image/png;base64,'+ base64;
$('#testDiv').append(image);
</ui:repeat>
it gives me a console error in inspect element
GET data:image/png;base64,_9j_4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP_sABFEdWNreQABA…CAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgP__Z
this is whats written in the js when i inspect element
blob = '_9j_4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP_sABFEdWNreQABAAQAAAA8AAD_7gAOQWRvYmUAZMAAAAAB_9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwMDBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx__wAARCADLAMgDAREAAhEBAxEB_8QAsgABAAIDAQEBAAAAAAAAAAAAAAUGAwQHAQIIAQEAAgMBAQAAAAAAAAAAAAAAAwQCBQYBBxAAAQQBAQQFBQsHDAMAAAAAAQACAwQRBSExEgZBUWEiE3GBkTIHobHB0UJSYnIjFBWCkqKyM3M28MLSQ5OzJDRUdDUW4eIXEQACAQMABwQJAwUAAwAAAAAAAQIRAwQhMUFREgUGYXGBwfCRobHR4SIyE2IUNPFCUjMWcoIV_9oADAMBAAIRAxEAPwD9UoAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAxy2K8X7WVkf1nBvvr1I8cktZi_FNN_1cP8AaM-Ne8L3GP5I70Zop4JRmKRsg-iQfeXjRkpJ6j7Xh6EAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEBHaprlSgC1x8Sfoibv_ACj0LOMGyK5eUe8rF3mHU7RI8TwY_mR930neplbSKU78pEaSSck5J3krMhPEB61zmkFpII3Eb0BJ0eY9SrEBz_Hj6WSbT5nb1g7aZNDIku0tGmazT1BuIzwTAZdC7f5usKCUGi7buqRvrElCAIAgCAIAgCAIAgCAIAgCAIAgCAhuYNc-5N-71zm04ZJ3hgPT5VJCFSvfvcOhaynPe57i55LnOOS47SSrBr2zxAEAQBAEB9RyPje18bi17TlrgcEFAnQueg62L8fhTYFqMbfpD5w-FV5wobGze4tD1ksoycIAgCAIAgCAIAgCAIAgCAIAgNfULjKdOSw7bwDut63HYAvYqrMLk-FVOfzTSTSvlkPFI8lzj2lW0qGrbq6s-EPDd0zSbWoSFsQ4Y2-vK7cPjKxlJIkt2nPUWipyzpkDR4jDO_pc_d-aNihdxsuxx4rtNz8L0zGPukP9m34ljxPeSfjjuRpXOWNNnaTE015OhzNoz2tPwLJXGiKePF6tBV9S0u1Ql4JhljvUkHqu_wDKnjJMp3Lbi9Jpr0jMtaxLWnZPEcSRnIPwI1U9jJp1R0Clajt1Y7EfqyDOOo7iPMVUaozawlxKpmXhkEAQBAEAQBAEAQBAEAQBAEBWecLR4oKoOzBkePcb8KmtLaU8qWpFaUxTM9GpJbtx12b5DgnqG8nzBeSdEZQjxOhdp59O0TS3TSnwqtZuXHpJ-FzitdlZMbUHcm_pRusbGlckrcFpZyrmDnvWtVlc2KV1OnnDIIiWkj6bhtPvL55n89v320nwQ3LzfojucLk9myqtcU978kVwSSB_GHEPzniBOc-Vafida7Ta8KpQs_LvP-saZKyO1I67Szh0ch4ntHWx52-Y7Fu-X8-vWGlN8cNz1-DNRncmtXlWK4J9mrxR1LNDWdMa-NwlrWG8Ucg3jt7CCvoWPfjcipwdYs4bIx3FuE1Roo1qtJWsSQSevG4tPb2-dbBOpppRo6GJDwtHJ9omOeq4-oRIwdh2O-BQ3VtLuLLQ0WNQlsIAgCAIAgCAIAgCAIAgCAICk8zvLtYmB-QGNH5oPwqzb1GuyH9bIpZkBYOT4A61PMRtjYGj8s_-qiuvQWsVaWyF9q-pSeJS01pxHwmxKOskljPRhy4XqrJdYWlq-5-5eZ3PTdhUlc26vN-Rz1cedQEAQHSPZRqUj69zTnklkJbND2B-Q8ekArtelcluM7b2aV46zkuo7CUo3Ft0PyJHm6FrNQjkH9ZGOLytJHvYXbWnoOKyl9VSCUhWJjlSQt1UN-fG5vvO-BR3dRYxn9Rc1XNgEAQBAEAQBAEAQBAEAQBAEBSOZWkazOT8oMI_MA-BWbeo1uR97ItZkJY-TZQJrMXS5rXDyNJH85RXkW8R6Wiue1ik9t-ldx9nJEYSeoscXe7xrgeq7LVyFzY409Tr5nd9N3VwShtTr6_6FDXJnShAEB0P2TU5OLULhGI8Mhaegu2ud6NnpXY9KWX9c9mhefwOW6kur6IbdLJjnCRpuwxjeyPJ_KJ-Jdza1HD5T-pEApSqS_KzC7V2n5jHE-jHwrC7qJ8ZfWXRVjYhAEAQBAEAQBAEAQBAEAQBAVXnCsW2IbIHde3gce1pyPcKntPYUcqOlMrylKpt6VeNK9HPvaDiQDpadhXko1RnbnwyqW3W9Ipa9pLqsju5IA-CZu0tdjuvH8ty1GfgxybTty8HuZv8LMlYuKcf6o45rWgano9kwXYi0ZIjmG2N462u-DevmubgXcaXDNdz2PuO_wATNt341g_DaiOVItEnoXLmqa1ZEVSM-GD9rYdsjYO09fYNqv4PLruTKkFo2vYinmZ1vHjWb07trOyaXp1HQtIZWjPDBXaXSSHe529zj2k_EvpWFhxsW1bhs9r3nz_My5Xpu5L-hTdQuOuXJbDtnGe6Opo2AehbWKoqGjuT4nU1l6YFl5OrHisWSNmBG0_pO-BQ3XsLmLHWyzKEuBAEAQBAEAQBAEAQBAEAQBAaWsUBeoSQj9oO9EfpDd6dyyhKjI7sOKNChOa5ri1ww4HBB3ghWjVniAl9G1-Wh9jKDJVJzwj1m5-b8SwnCpPavuOh6i0RXNL1GExh0c7H-tC8A-ljlVuWk1SSqjYWr-msXRmsOVOWhJ4n4ZX4urw28P5uMKj_APKxa1_HH1F7_wCjkUpxy9ZsT6hpenRcDnsiDNjYYwM-QNar9u1RUiqIoXLyrWT0lV1nXZtQPhtBjrNOQzpd2uVmEKGvu3nLuItZkJ9RsfI9rGDie4hrWjpJ2BAlUv8AplJtKlHXG1zRl563HaVVk6s2tuHDGhtLEzCAIAgCAIAgCAIAgCAIAgCAICt8yaG55derNy7fPGOn6Q-FTW57GU8iz_cisKYphAEB9-NMW8PG7h6snCUPas-EPAgCAtfLmhugxcstxKR9lGfkg9J7VBcnXQi9j2aaWWBRFoIAgCAIAgCAIAgCAIAgCAIAgCAICD1blmGy501UiKY7XMPqOPm3FSxuU1la7jp6VrKxboW6j-GxE6PqJGw-Q7iplJMpSg46zXXpiEAQGzT0-5cdw14nP63bmjyuOxeOSRnG25ai06Ry3BULZrBE1gbQPkNPZ1ntUErlS7ax1HS9ZMqMsBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQHjmNe0tcA5p3gjIQNGhNoGkSnLqzWnrZlnuNICzU2ROxB7DB_1bSM54H46uIr38rMf20DYh0HSYTltZpPW_L_ANYleObMlZgthvNa1oDWgBo3AbAsCU9QBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAfMsjIo3SPOGMBc49QAyUR43Qq1Pmi47UGeO4Cq9-C3AHCHbBt7FO7aoUoZL4tOotagLwQHjnNa0ucQ1rRkk7AAF43TSz1KpR9e9p9StI6DSohae04Nh5Iiz9EDvO9xctndTQg-GyuN73q-fsOiw-n5TXFdfCt235FcPP3Olok1n8Izuhga4Ds7zXrTPn2dc-1-qK-DNsuTYkPuXrl_Qy1PabzHXkxaZFYaPWa9nhu8xbjHoWdrqXJg_rUZeFPcYXOn8eS-luPjUvPLfOWla4PDjzBcAy6tIdpA3ljtzh7vYuq5dzi1laF9M_8AF-W85zP5Xdx9L0w3_HcTy2xrDllz2l8xQ254mNr8McjmNyx2cNcQPlLgr3UmTGbS4dDez5nZ2uQY8opvi0rf8jD_APUOZfm1_wCzd_SUf_T5X6fV8zP_AJ7H_V6_ket9qXMgOTHWcOosfj3HherqjJ3Q9T-IfT2Pvl618Cx8u-0qrfsMqajCKk0h4Y5mnMRcdwOdrc-dbnl_UkLslC4uBvbs-Rqs7kMrcXK2-JLZt-ZdV05zxWYdf1F-riqXN8IzGPHDt4eLG9TOCpUpq_Ljp2lmUJcCAxWpHR1ppG-sxjnN8oBK9Wsxk6JkFoGt37t4wzlpZwF2xuNoIUs4JIrWL0pSoyxKEthAEAQBAQfNd7waTazT37B731G7T6SpbUdNStkzoqbytS6fNFQhuO_ZzOc0dmN3p2qZS00KbttRTLhoF775p0bnHMsf2cnlbuPnCrzjRl-xPiiSKwJjnntN5kka5uiVn8ILQ-44bzna2P8AnHzLjupuYtP8EX2y8l5-o6np_ATX5pf-vm_Iw8h8j1rdduq6ozxIXn_C1j6rgDjjf1jO4KPkXJI3I_muqq_tXmyTnHN5Ql-K26Pa_JHR4ooooxHExscbdjWNAaAOwBdnGCiqJURykpOTq3Vmlq2haVq0Biu12yZGGyYAkb2tfvCrZeDayI0uRr27fBk-NmXbLrB093qORcwaLe5a1kMjkcAD4tOy3YS3Ozd8obivnfMMK5hX6J9sX6bTucLLhl2atdkkdV5V10a1o0Vw4E4zHYaNwkbv9IIK77lWd-5sKf8Adqff6aTi-Y4f7e84bNa7jDz1_CeofUb_AHjVFzz-JPuXvRJyf-VDv8mVD2Tf8jf_AHLf1lzvSn-yf_iveb3qT_XDvOlSRxyMLJGh7HbHNcAQR2grt5RUlR6UcjGTTqjjfPml09N5hkhqNEcMjGy-E3cwuyCAOgbMr5tz3FhZyXGGhNJ03He8myJ3bCc9LTpXedX5fsS2dD0-eXJlkrxOeTvJLBk-feu_wLjnYhJ63Fe44rNgoXpxWpSfvKtW_iJv-5P662j-00kf9niXhVjZBAYL_wDkbH7p_wCqV7HWYz-1lV5T_wCUP7p3vhT3dRRxvuLiq5sAgCAIAgKRqMr9V1rgiOWucIoj1NB9b3yrMVwxNbcfHPQWu7p0U-mOpMGAGARdhb6vvKBSo6l6dtONCs8s3XVdRNeTusn7jgeh49X4lNcVUU8efDKm8uSrmwOGcyTPucyag_OS-y9jc9TXcDfcAXyvmM3cyZvfNr20R9GwIKGPBfpXxO3Va0dWrDWiGI4WNjYB1NGAvqFq2oQUVqiqHzy5cc5OT1t1MqkMAgKZ7U6ccuhQ2cfaV5wA76MgIcPSGrmuqLKljqW2Mvf6I3_Tt1q847JR93oyN9ktl3iajVJ7pEcrR1EFzT6chUek7jrch3P3lzqW3ohLvRaOev4T1D6jf7xq3vPP4k-5e9Gm5P8Ayod_kzmHKvNEnL9ieZlcWDOwMILi3GDnoBXDcr5m8STko8XEt9DsOY8vWTFJvhoWKT2tXSwiPT42v6HOkc4egBvvrcy6rnTRBV7zVR6ahXTN-ohdN0bXebNWdbmDhHK7Ni45uGNaNnCzrIGwALWY2HkcwvcctTemWzw-Bsb-VZwrXCta1R2-J2GCCOCCOCIcMUTWsY3qa0YAX0a3BQiorUlQ4Oc3KTk9bKVW_iJv-5P66uP7TVx_2eJeFWNkEBgv_wCRsfun_qlex1mM_tZVeU_-UP7p3vhT3dRRxvuLiq5sAgCAICO1-99002RzTiSX7OPyu3nzBZwjVkN-fDEptG9LSsCeINMgBA4hkDPnCsSVTXwm4uqJL_tmqdUX5p-NYfiRN-5kRdi1JNZdZOGSPdxng2Di6wpEqKhDKVXUvemXW3KMVges4YeOpw2FVZKjNnbnxRqcZ5qrSUuZtQZjhIndKzySHxG7-xy-V80tu1lTX6q-vSj6Ry64rmPB_pp6tB2mhciuUoLcRzHPG2Rv5Qyvpti8rkIzWqSqfPr1p25uL1p0M6lIwgKT7VL8cWj16eftbE3Hj6EYOf0nBcx1TfUbMYbZS9i9EdD07ZbuueyK9rNL2S1HcOoXCO6THCw9oy53vtVXpSzonPuXm_IsdSXfsh3v09pZuev4T1D6jf7xq3fPP4k-5e9Go5P_ACod_kyk-zGhQuX7rblaKy1kTS1szGvAPFvHECuY6ZsW7lyanFS0bVXadD1BenbhFwk46djobXtK5arVY6-pUK7IIf2NiOJoY0E7WO4WgDbtBPkU_UnLY21G7biox1Oip3P07CHkOfKbdubbetV9vp3lh9nmuDUtDbXkdmzRxE_rLMfZu9Ax5luOn8781jhf3Q0eGz4eBq-d4f4r3Evtnp8dpaFvjTFHr7OYm52f4oj9NWX9prY_7PEvCrGyCAwagQKFkncIn5_NK9jrMZ_ayq8pAnVHdkTs-kKe7qKOL9xcVXNgEAQBAU_me46zqIrR95sHdAHS92_4lYtqiqa_InWVNxZdOoR1aUUBaC5re-cA5cdp91QylVly3BRjQ2fCi-Y30BY1M6I0Nb05lrTpGMYPFZ348DblvR5ws4SoyK9b4okNyle4J303nuy9-P6wG30j3lJdjtK-LOjoR_tK5ZktRN1iozilgbwWmNG0xjaH_k9PZ5FxvUnLXcX5oLTH7u7f4e7uOy5DnqD_ABSeh6u_d4-mshuRueI9LZ-HaiT9yJJhmALjETvBA28J37FreSc7Vhfiu_Zse75F_m_KHef5Lf37Vv8AmdMqXqVyMSVZ452EZDo3B3vLuLV-FxVhJSXYchcsztukk0-0j9Z5r0TSYnOs2GvmA7teMh8hPkG7ylU8zmtjHVZS07lpfp3lrF5devv6Y6N71HKNRv6rzTroc2MummIjrwN2hjB0Z7N7iuAyL93Pv6F9T0Jbl6a2drYs2sOzpehaW979NR13l7RotH0mCjGeJzBxSyfOkdtcfi7F9D5fhrGsq2tmvte04fNynfuub8O4jed7tN_K-oRsnjdIWtAYHtLsiRvRlUud3oPFmlJVpv7UW-UWprJg2nTu7GVL2WWIIdQvGaRsYMTQC9wbnvdq5_pe5GNyfE0vpXvN31FCUoRoq6Tol-nU1XTJ6rnNkgssLONpDgD0OGOlrhldjkWYZFpwemMl6eo5WzdlZuKS0Sizk_LGoTct80eFb7kfGatwdABOOLzEA56l8_5ZkSwsuk9Crwy-Pn3HbcwsLLxqx1_dH4HX4rlSZ3BFPHI7GeFjmuOPICvosb0JOiaficLK1KKq00VHmGnLT1M2WZDJXeJG8dDxtPu7Vctuqoay_BxlUn9M5gpW42iR7YbG5zHHAJ-iTvUUoNFq3fUu8kHWK7G8T5WNb1lwAWNCVyRX-YNfrvrvqVHeIX7JJR6oHUD05UtuG1lS_fTVEffKVF8cUlt4x4vcj-qN585Xl2Ww9xYUVSwqIthAEB4_j4HcGOPB4c7s9GUDK_p_LViLUGWrUrJA1xeQM5L94O0Dp2qaVzRRFSGO1KrLCoS2EAQFdl5ZtN1E2qksbGh_iRtdnIO_GwblMripRlR474qosXRt84UJbObe0DQuVqT_AB2SPq35wXtrQsD2O2-sQS0M29R8y4nn-DiWnxJuNyWxKqfup6aDreS5mTcVGlKC2t6fn6aSgrkjpia5f0HTtTkDbWrQUjnbG8O4yOwu4GbfrLacvwbV9_XdjDsev20XtNfm5lyyvptyn6eL9h1Tl3QND0iLg0_hkmeMyWC4PkcPKNw7Au95dgWMdUt6Xv1tnF52bevutzQt2wmVsigc0tey3V5rU0zbdcNke54B484cSfmriLvS96U2-KOl9vwOut9Q2oxS4ZaF2fExf_KNZ_1lf9P-io_-Vv8A-Ufb8DP_AKO1_jL2fEvnLGkzaTodbT5ntklg4-J7M8J45HPGMgHc5dZyzElj2I25OrjXV2ts5rmGSr96VxKidPckQHOHIU-s6k29Tmihe5gbYbJxd5zdjXDhB6NnmWo5vyGWTd_JBqLppqbTlnOVYt8E03p0UPnk_kbUNE1Y3bFiGWMxOj4Y-LOXEHpA6k5RyO5i3uOUotUpoqOZ83t5FrgimnWukuFqrBahdDOwPjd0HoPWF06dDnZRUlRldtcnv4ias4LTubLkEedoPvKZXd5Uli7mazeUtTJ2viaOviPwNXv5UYftZEjR5SrxvD7UnjEbfDaOFvn6SsJXdxNDFS1k-1oaA1ow0bABuAURaCAIAgCAIAgCAIAgCA17On0bUkUtmvHNJASYXPaHcJdvxnyKG5j25tOUU3HVXYS2784JqLaT1mK9omkXozHbpxStxgEtAcPI4YcPMVHfwrN1UnGL8DOzl3bbrGTRTtU9lNd7y_TLZhB_qZhxtHkeNvpBXOZXSsW62pU7Hp9pvsfqOSVLka9q-BO8mcqnQKkzZntltWHgySMzgNaMNaM4PSStpyblf7SDUmnOT2bthrua8x_czVFSMSwrcmqCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAc42b-hAVyDm2SV8UIq4nlEcfDxHAscbG2Izs3RNlDs9O3ZsQG1qPMLqN41XwcWDC_jDjsgk4_ElOz-r8M58oQHkvMLodMq6jLBivZMhOCctj4HyQndveGNGOtyAz6PrEmoOlDoREK7WMnPFnhs5cJotw2M4W7enKAxa7rs-nNsmCBsxp1X3Z_EeWZY3IDWYa7Lu6f5FAe6zrstCwytBVfamdE-csY2VxLWEDhb4bJO87PysAdKAyPvXv-wVqbGsFOSrJPJxZEgc17WjHR8tARFLnptnmkaIKzXQSyTwwXI3vIMlZvHI1wdGxu75rjhAYH8_TnXG0I6LDVOo_hZndNiXxGjL3-Fw-rt2HKAla_MNyfmu3osdNpr02RyTXPEwQJWFwHBjbl2zegI2jz2-1qVSl91Y02b9uk4iTJa2q0OD8Y-VncgLJql8UabrHB4jg-ONjCeEF8sjY2cTsHhHE8ZONgQGG5qFupVg8SKN1yxM2CNge4RBziTkvLc4DW59XfsQGs7Xp_wAP8Ztdv3kWxRfFxnw_EMvhcQfw5LdufVygPNL163atxwWKzIWzG0xjmSF546UwhkyCxmxzslvYO1ATSAIAgCAIAgCAIAgCA126fRbI2RteMSMkfMxwaMiSQEPeD1uDjkoD6mpU53ufNCyR7o3QOc4AkxPxxM-qcbQgPZKlWSFkEkTHQsLCyMgcIMZDmYH0S0YQHyaFEwzwGCMw2S51iPhHDIXjDi4dOelAaetaDX1ZrY7Bb4XC6OTMbHPLH44g17hlucfyIBQG5aoUrfB95gZN4eSwvaDjO_GevG1Afb6teSeKw-Nrp4Q4RSEd5oeMOAPbjagNWPQtFjv_AIhHRgZeLnPNlsbRJxPHC48QGckHagNLU-UtKu6lU1FsbK9ytZZZkmjY0PlMYIDXu34QErHSqR2pbccLG2Zw1s0wADnhmxocenCA1maBojLxvsoQNul5kNlsbRIXkEF3EBnJyUBsmlTMc0RgjMVgl07C0Fry4YcXA7DkDpQHz-HUPun3M12Grv8ABLQW5zxZweni2oD1tGk2COBsDGwROD4ow0BrXNdxAgDpDtqA9jpVI3tfHCxr2GRzHAAEGZ3HIR9d20oDMgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgP__Z';
image = document.createElement('img');
image.src = 'data:image/png;base64,'+ blob ;
UPDATE 2
ahh! fixed it! now its working.
changed Base64.encodeBase64URLSafeString(rawLogo); to Base64.encodeBase64String(rawLogo);
I wouldn't be surprised if the problem is that the way the JSP renders item.logo on the page is messing it up. Since you have no use for the byte array in JavaScript, you can convert it in Java before printing it on the page. Also, this relieves the need for window.btoa, which isn't natively supported in IE before version 10.
Try creating a method in your class that returns the base64 encoded value of the logo property, called something like getLogo64...then in your JSP, you can reference it like: base64 = "#{item.logo64}"; and not even deal with the logo property. So an example is:
public String getLogo64() {
return Base64.encodeBase64String(this.logo);
}
At the same time, you can add a basic method that accepts a byte[] and converts it (which is what you have found to work):
public String RenderLogo(byte[] rawLogo) {
String base64String = Base64.encodeBase64String(rawLogo);
return base64String;
}
and use it like #{testController.RenderLogo(item.logo)}.
Reference:
encodeBase64String: http://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/binary/Base64.html#encodeBase64String(byte%5B%5D)
If the resource you're loading has the appropriate protocol and CORS headers available, you could load it as a Blob, then add it to your document like this using the URL.createObjectURL(data) method to get the img src:
function urlToDataBlob(file_url, callback){
var xhr = new XMLHttpRequest();
xhr.open('GET', file_url, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
console.log('urlToDataBlob: load: ', e);
if (this.status == 200) {
callback(this.response);
}
};
xhr.send();
}
// eg:
urlToDataBlob('https://the.url/to.some.jpg', function(data){
console.log('data: ', data);
var _img = '<img src="'+ URL.createObjectURL(data) +'">';
// add to your document..
});
See : https://www.html5rocks.com/en/tutorials/file/xhr2/

using xmlhttprequest to fetch a cross-domain PNG file

Sadly, I see a zillion similar questions but no answers that seem specific to my situation. I am not using jquery. I don't care about anything but the newest browsers (Chrome in particular). I am looking for a way to load a javascript Image from a cross-domain fetch of a PNG or JPG file.
i.e. I just want to do this:
var img1 = new Image();
img1.addEventListener('load', function() { imageLoaded( canvas, context, this); }, false)
img1.src = textureUrl;
which works great for same domain. However, apparently that will not include the Origin tag in the request header, so it is unable to work in a cross-domain environment, even though we have successfully set up the CORS headers on the servers. If there is something simple I can do to this request to include that header, that would be great.
But I gather what I have to do is use XHR to do an async fetch of the asset, to get the binary data, and then somehow shove that data into a regular Image() object. I believe we have successfully obtained the data in various forms (tried arraybuffer and blobs), but are not successful in jamming it into the Image() object.
For example:
var img3 = new Image();
var req = new window.XMLHttpRequest();
req.overrideMimeType('text/plain; charset=x-user-defined'); // seems to make no difference
req.responseType = 'arraybuffer'; // no joy with arraybuffer or blob
req.open("GET", textureUrl, true, "", ""); // async request allows CORS preflight exchange
req.onreadystatechange = function (oEvent) {
if (req.readyState === 4) {
if (req.status === 200) {
alert( "XHR worked" );
if( req.response ) {
alert( "resp text: " + req.response ); // identifies response as arraybuffer or blob
}
// I believe this section is where I need the most help.
// var base64Img = window.btoa(unescape(encodeURIComponent( req.responseText)) );
var base64Img = window.btoa( unescape( encodeURIComponent( req.response ) ) );
alert( "b64: " + base64Img ); // vaguely uu64ish, but truncated
var src = "";
if( isPng == 1 ) { // just to indicate the src url is built differently for jpg.
alert("png");
src = 'data:image/png;base64,' + base64Img;
}
....
img3.src = src; // img3 loads fine if I just jam a same domain url here
<closing braces>
From what I have read, it isn't clear I need to override the mime type, if I specify arraybuffer, but it isn't clear to me.
I get data back (no cross-domain errors, yay), and it seems to be about the right size, but I am not convinced I am successfully uu64 encoding it, nor that I am jamming a suitable data url into the image.
Again, I only need this to work with the newest Chrome browser, and I would like to be as 'pure HTML5' as possible, so I don't feel the need to work with IE7, etc.
I don't know if req.response includes the first line of the HTTP response or not (i.e. is it my responsibility to trim something before uuencoding it...)
Hope you can pull the wool from my eyes!
Thanks in advance.
I got stuck on the same problem for some time. This is what you need to do to make it work:
For zip/png etc. formats, you should use:
req.responseType = 'arraybuffer';
The tricky thing is in case of arraybuffer, req.responseText doesn't work but instead use req.response
var base64Img = window.btoa(
unescape(
encodeURIComponent(req.response)
)
);
If you are happy with using the latest HTML features, the following could help.
Loading binaries using Fetch API:
const response = await fetch('https://cross-origin.org/path-to-binary.png' , {
cache: 'no-cache',
mode: 'cors',
credentials: 'omit'
});
if (!response.ok) {
console.error(response);
throw new Error(response.statusText);
}
console.log('response from fetch', response);
const blob = await response.blob();
To convert Blob to base64 you can use the FileReader API
// Lang: Typescript
private async convertBlobToBase64(blob: Blob): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onerror = reject;
reader.onload = () => {
resolve(reader.result as string);
};
reader.readAsDataURL(blob);
});
}

How to get a file or blob from an object URL?

I am allowing the user to load images into a page via drag&drop and other methods. When an image is dropped, I'm using URL.createObjectURL to convert to an object URL to display the image. I am not revoking the url, as I do reuse it.
So, when it comes time to create a FormData object so I can allow them to upload a form with one of those images in it, is there some way I can then reverse that Object URL back into a Blob or File so I can then append it to a FormData object?
Modern solution:
let blob = await fetch(url).then(r => r.blob());
The url can be an object url or a normal url.
As gengkev alludes to in his comment above, it looks like the best/only way to do this is with an async xhr2 call:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'blob:http%3A//your.blob.url.here', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var myBlob = this.response;
// myBlob is now the blob that the object URL pointed to.
}
};
xhr.send();
Update (2018): For situations where ES5 can safely be used, Joe has a simpler ES5-based answer below.
Maybe someone finds this useful when working with React/Node/Axios. I used this for my Cloudinary image upload feature with react-dropzone on the UI.
axios({
method: 'get',
url: file[0].preview, // blob url eg. blob:http://127.0.0.1:8000/e89c5d87-a634-4540-974c-30dc476825cc
responseType: 'blob'
}).then(function(response){
var reader = new FileReader();
reader.readAsDataURL(response.data);
reader.onloadend = function() {
var base64data = reader.result;
self.props.onMainImageDrop(base64data)
}
})
The problem with fetching the blob URL again is that this will create a full copy of the Blob's data, and so instead of having it only once in memory, you'll have it twice. With big Blobs this can blow your memory usage quite quickly.
It's rather unfortunate that the File API doesn't give us access to the currently linked Blobs, certainly they thought web-authors should store that Blob themselves at creation time anyway, which is true:
The best here is to store the object you used when creating the blob:// URL.
If you are afraid this would prevent the Blob from being Garbage Collected, you're right, but so does the blob:// URL in the first place, until you revoke it. So holding yourself a pointer to that Blob won't change a thing.
But for those who aren't responsible for the creation of the blob:// URI (e.g because a library made it), we can still fill that API hole ourselves by overriding the default URL.createObjectURL and URL.revokeObjectURL methods so that they do store references to the object passed.
Be sure to call this function before the code that does generate the blob:// URI is called.
// Adds an URL.getFromObjectURL( <blob:// URI> ) method
// returns the original object (<Blob> or <MediaSource>) the URI points to or null
(() => {
// overrides URL methods to be able to retrieve the original blobs later on
const old_create = URL.createObjectURL;
const old_revoke = URL.revokeObjectURL;
Object.defineProperty(URL, 'createObjectURL', {
get: () => storeAndCreate
});
Object.defineProperty(URL, 'revokeObjectURL', {
get: () => forgetAndRevoke
});
Object.defineProperty(URL, 'getFromObjectURL', {
get: () => getBlob
});
const dict = {};
function storeAndCreate(blob) {
const url = old_create(blob); // let it throw if it has to
dict[url] = blob;
return url
}
function forgetAndRevoke(url) {
old_revoke(url);
try {
if(new URL(url).protocol === 'blob:') {
delete dict[url];
}
} catch(e){}
}
function getBlob(url) {
return dict[url] || null;
}
})();
// Usage:
const blob = new Blob( ["foo"] );
const url = URL.createObjectURL( blob );
console.log( url );
const retrieved = URL.getFromObjectURL( url );
console.log( "retrieved Blob is Same Object?", retrieved === blob );
fetch( url ).then( (resp) => resp.blob() )
.then( (fetched) => console.log( "fetched Blob is Same Object?", fetched === blob ) );
And an other advantage is that it can even retrieve MediaSource objects, while the fetching solutions would just err in that case.
Using fetch for example like below:
fetch(<"yoururl">, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + <your access token if need>
},
})
.then((response) => response.blob())
.then((blob) => {
// 2. Create blob link to download
const url = window.URL.createObjectURL(new Blob([blob]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', `sample.xlsx`);
// 3. Append to html page
document.body.appendChild(link);
// 4. Force download
link.click();
// 5. Clean up and remove the link
link.parentNode.removeChild(link);
})
You can paste in on Chrome console to test. the file with download with 'sample.xlsx' Hope it can help!
See Getting BLOB data from XHR request which points out that BlobBuilder doesn't work in Chrome so you need to use:
xhr.responseType = 'arraybuffer';
Unfortunately #BrianFreud's answer doesn't fit my needs, I had a little different need, and I know that is not the answer for #BrianFreud's question, but I am leaving it here because a lot of persons got here with my same need. I needed something like 'How to get a file or blob from an URL?', and the current correct answer does not fit my needs because its not cross-domain.
I have a website that consumes images from an Amazon S3/Azure Storage, and there I store objects named with uniqueidentifiers:
sample: http://****.blob.core.windows.net/systemimages/bf142dc9-0185-4aee-a3f4-1e5e95a09bcf
Some of this images should be download from our system interface.
To avoid passing this traffic through my HTTP server, since this objects does not require any security to be accessed (except by domain filtering), I decided to make a direct request on user's browser and use local processing to give the file a real name and extension.
To accomplish that I have used this great article from Henry Algus:
http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/
1. First step: Add binary support to jquery
/**
*
* jquery.binarytransport.js
*
* #description. jQuery ajax transport for making binary data type requests.
* #version 1.0
* #author Henry Algus <henryalgus#gmail.com>
*
*/
// use this transport for "binary" data type
$.ajaxTransport("+binary", function (options, originalOptions, jqXHR) {
// check for conditions and support for blob / arraybuffer response type
if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob))))) {
return {
// create new XMLHttpRequest
send: function (headers, callback) {
// setup all variables
var xhr = new XMLHttpRequest(),
url = options.url,
type = options.type,
async = options.async || true,
// blob or arraybuffer. Default is blob
dataType = options.responseType || "blob",
data = options.data || null,
username = options.username || null,
password = options.password || null;
xhr.addEventListener('load', function () {
var data = {};
data[options.dataType] = xhr.response;
// make callback and send data
callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
});
xhr.open(type, url, async, username, password);
// setup custom headers
for (var i in headers) {
xhr.setRequestHeader(i, headers[i]);
}
xhr.responseType = dataType;
xhr.send(data);
},
abort: function () {
jqXHR.abort();
}
};
}
});
2. Second step: Make a request using this transport type.
function downloadArt(url)
{
$.ajax(url, {
dataType: "binary",
processData: false
}).done(function (data) {
// just my logic to name/create files
var filename = url.substr(url.lastIndexOf('/') + 1) + '.png';
var blob = new Blob([data], { type: 'image/png' });
saveAs(blob, filename);
});
}
Now you can use the Blob created as you want to, in my case I want to save it to disk.
3. Optional: Save file on user's computer using FileSaver
I have used FileSaver.js to save to disk the downloaded file, if you need to accomplish that, please use this javascript library:
https://github.com/eligrey/FileSaver.js/
I expect this to help others with more specific needs.
If you show the file in a canvas anyway you can also convert the canvas content to a blob object.
canvas.toBlob(function(my_file){
//.toBlob is only implemented in > FF18 but there is a polyfill
//for other browsers https://github.com/blueimp/JavaScript-Canvas-to-Blob
var myBlob = (my_file);
})
Following #Kaiido answer, another way to overload URL without messing with URL is to extend the URL class like this:
export class URLwithStore extends URL {
static createObjectURL(blob) {
const url = super.createObjectURL(blob);
URLwithStore.store = { ...(URLwithStore.store ?? {}), [url]: blob };
return url;
}
static getFromObjectURL(url) {
return (URLwithStore.store ?? {})[url] ?? null;
}
static revokeObjectURL(url) {
super.revokeObjectURL(url);
if (
new URL(url).protocol === "blob:" &&
URLwithStore.store &&
url in URLwithStore.store
)
delete URLwithStore.store[url];
}
}
Usage
const blob = new Blob( ["foo"] );
const url = URLwithStore.createObjectURL( blob );
const retrieved = URLwithStore.getFromObjectURL( url );
console.log( "retrieved Blob is Same Object?", retrieved === blob );

Categories