1

I am using the below code to call a captcha generating web service. The response is fetched correctly but when trying to append the result under a div the image appears as garbage text

var xmlHttp = new XMLHttpRequest();
          xmlHttp.onreadystatechange = function() { 
              if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
               { 
              window.alert(xmlHttp.getAllResponseHeaders()); 
                 document.getElementById("captchaDiv2").innerHTML = "<img src=\"data:image/png;base64," + xmlHttp.responseText + "\"/>";
               }
          }
          xmlHttp.open("GET", captchaSrc, true); // true for asynchronous 
          xmlHttp.send(null);

The response header is the below, as you can see the type is image/png

Response header Yet when I try to import it inside the html I am getting the below: Result on the UI

Can you please advise what could be the root cause behind this? I already tried btoa() with and without encoding... No results.

erahal
  • 433
  • 4
  • 17
  • How about removing all javascript and putting `` – Alex K Mar 21 '17 at 10:49
  • Cannot do that because I need to parse the header and remove some info (the captcha) from it for further validation. If there is a way to fetch the header's infor with what you suggested then it would be a valid solution – erahal Mar 21 '17 at 12:46

1 Answers1

4

This answer uses the information from https://stackoverflow.com/a/11562550/266561 - long story short: the string you get in XHR is a bit hard to convert to base64 because the string seems to be converted to UTF-8 and then it seems corrupted, and base64 string is no longer valid. Moreover, if you try to btoa(xmlHttp.responseText) you get error in Chrome because of non-ascii characters..

BUT, there is a solution. First, make an empty <img id="captchaImg" /> element for simplicity of embedding the new src. Then,

var xmlHttp = new XMLHttpRequest();
xmlHttp.responseType = "arraybuffer";
xmlHttp.onreadystatechange = function() { 
  if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { 
    document.getElementById("captchaImg").setAttribute('src', 'data:image/png;base64,' + btoa(String.fromCharCode.apply(null, new Uint8Array(xmlHttp.response))));
  }
}
xmlHttp.open("GET", captchaSrc, true); // true for asynchronous
xmlHttp.send(null);

The trick here is xmlHttp.responseType = "arraybuffer" to ensure our data is kept safe and not garbled. As of compatibility point of view, if I understand correctly from MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays), the support for typed arrays is from IE 10 and is even supported in old Safari 5.1 (which was the last version for Windows).

Community
  • 1
  • 1
Alex K
  • 6,737
  • 9
  • 41
  • 63