0

How can the plain text response of an XMLHTTPRequest be converted to a dataUrl on client side?

Image data is being send from the server to an Iframe and the only option to retrieve the data is the default encoded data from a GET request.* I do not have any control over the server. I can not specify overrideMimeType nor the responseType of the request.

I tried to utf8 encode the returned data:

const utf8 = new TextEncoder();
const bytes  = utf8.encode(imageDataAsText);

//Convert to data url
const fr = new FileReader();
const blob = new Blob([bytes], { type: attachment.metadata.mediaType });
fr.onload = (e) => {
   setImageData(fr.result as string);
};
fr.readAsDataURL(blob);

Converting via the char code didn't work either: https://stackoverflow.com/a/6226756/3244464

let bytesv2 = []; // char codes

for (var i = 0; i < imageDataAsString.length; ++i) {
   var code = imageDataAsString.charCodeAt(i);
   bytesv2 = bytesv2.concat([code & 0xff, code / 256 >>> 0]);
}

Raw data as it is displayed by console out. What is the actual default encoding of the data I am working with here? Recieved data

Context:

* The data in question is recieved inside an iframe inside the atlassian (jira/confuence) ecosystem. They do not support piping binary data from the parent frame to the iframe, nor can I make my own request due to the authorization flow which requires cookies stored on the parent page. All other options mention to override some encoding, or changing it on the server side do not apply in this specific case.

Kilian
  • 1,540
  • 16
  • 28

1 Answers1

0

When you are using XMLHttpRequest to get binary data then don't return it as a string. Use xhr.responseType = 'blob' (or arrayBuffer if you intend to read/modify it)

var xhr = new XMLHttpRequest()
xhr.responseType = 'blob'
xhr.onload = () => {
  // Convert xhr blob to data url
  const fr = new FileReader()
  fr.onload = () => {
    setImageData(fr.result)
  }
  fr.readAsDataURL(xhr.response)
}

Better yet use the fetch api instead of the old XMLHttpRequest to get the binary It's more popular among web workers and servers. It's also simpler and based on promises

fetch(url)
  .then(res => res.blob())
  .then(blob => { ... })

And why do you need it to be a base64 url? if it's just to show a preview of an <img> then it's a waste of time, cpu and memory. It would be better just to do:

img.src = URL.createObjectURL(blob)
Endless
  • 34,080
  • 13
  • 108
  • 131
  • Please see second section of my question. In my case I am not able to set the responseType of the request and only got the text to work with. (this is due to some funky iframe parent bridge) The URL.createObjectURL(blob) is a good suggestion. Thanks – Kilian May 15 '21 at 10:12
  • Hmm, missed that part then if you can't make the request yourself then you are unlucky. i'm afraid i don't have a answer for u other than to make a feature request to support binary data – Endless May 15 '21 at 10:30