Img src path with header params to pass
Asked Answered
H

4

33

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?

Huth answered 12/5, 2014 at 13:8 Comment(3)
If you posted some code, I'm sure I could steer you in the right direction (ideally the <img> tag as well as the function in the jsp page).Adamandeve
Why does the image require header parameters to work?Antefix
BTW, people complaining about the lack of code, I'm not sure it would be helpful given the question. At least not yet.Antefix
C
20

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?

Captivate answered 12/5, 2014 at 13:35 Comment(1)
The only performance impact I've noticed is when opening devtools (because the base64 data url can be big). However, since this answer the blob api has become standard, so you can use that instead of data urls now for better performance.Captivate
G
48

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);
});
Gantlet answered 26/1, 2018 at 11:49 Comment(2)
Finally I found this! This works perfectly fine and fast. All other methods based on XMLHttpRequest or converting the bytes of image to Base64 to are too slow for my needs. Note that 'fetch()' perfectly sends parallel requests like a regular <img src="..."> does, while XMLHttpRequest is limited in parallelism and makes the images to wait in queue. Thanks so much!Godsend
The MDN docs says that you should also free the object URL using URL.revokeObjectURLArsenide
C
20

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?

Captivate answered 12/5, 2014 at 13:35 Comment(1)
The only performance impact I've noticed is when opening devtools (because the base64 data url can be big). However, since this answer the blob api has become standard, so you can use that instead of data urls now for better performance.Captivate
O
8

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]">

Olindaolinde answered 12/5, 2014 at 13:36 Comment(4)
Your idea about adding the token as a param was spot on. Thanks!Areta
Sending a token in the URL is bad practice.Goddord
As a url parameter should really be extremely last resort, it is bad practice as it can expose the token through browser history, referrer header etcGrizel
Also you'll lose the browser cached image every time your token changes - which should be often...Buhrstone
S
7

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));" />
Spatter answered 17/3, 2020 at 17:41 Comment(3)
If the fetch fails wouldn't that lead to infinite onerror loop?Ruching
@DrorBar probably onerror handler is executed only if errors occurs during load image using path given in src attribute (but I don't check this deeply). Code inside onerror not handle any future errors.Pokorny
This code is using modern JavaScript features, so it may not work in older browsers. It is also worth noting that this approach may cause security concerns, as it allows executing arbitrary JavaScript code on an error event.Richierichlad

© 2022 - 2024 — McMap. All rights reserved.