9

I am using this

        $.ajax({
            type: "GET",
            url: 'template/bump1/purse.png',
            datatype:"image/png",
            success: function (data) {


                var reader = new FileReader();

                reader.onload = function (e) {
                  var img = document.getElementById("CaptchaImg");
                  img.src = e.target.result;
                };
                reader.readAsDataURL(data);


                //$('#CaptchaImg').attr('src', data);
            }
         });

to download an image, and it comes out in binary, looking like this

enter image description here

node.js is returning it as

                        WriteHeaderMode('image/png', res, 200);
                        res.end(data, 'binary');

But now, how do I put that into an image tag and show it as an image. Note: I do not want to have return data as base64 encoding, it has to be binary. Im fine with converting the binary into base64 on client side though.

When I pass it to the readAsDataURL, it says TypeError exception.

Thanks

EDIT

                var img = document.getElementById("CaptchaImg");

                  var reader = new FileReader();

                  reader.onload = function(e) {
                      //img.src = e.target.result;
                      $("body").html(e.target.result);
                    };

                  reader.readAsDataURL(new Blob([data]));

this seems to convert it into a base64 encoding, which starts as data:application/octet-stream;base64, but doesn't display an image...

sneaky
  • 2,141
  • 9
  • 31
  • 38
  • I haven't researched this much but I'm guessing since `application/octet-stream` is basically saying "download me", you might try doing a straight up `.replace("application/octet-stream", "image/png");`. Worth a shot lol – Deryck Aug 19 '15 at 03:48
  • I tried it, but it didn't work. – sneaky Aug 19 '15 at 03:49
  • well at least I know I wasn't crazy for suggesting it. But instead of trying to fix that as the problem, maybe try re-thinking the logic? Just by setting the `src` attribute to the image URL you'll initiate the download of the image so instead of AJAX just do that – Deryck Aug 19 '15 at 03:53
  • I dont want to do that, because I may not have it here, but I am also sending a `FormData()` as an attachment which has an image. i.e. I am trying to upload and download an image in the same ajax call. – sneaky Aug 19 '15 at 03:55
  • I tried your solution, but I used angular $http, and set responseType to 'blob'. Then it worked with your solution but using `reader.readAsDataURL(data.data);`. The actual data being a property on the response object. I'm not sure if this is just a difference on how jQuery and angular works. – awe Jan 25 '17 at 08:22

4 Answers4

5

jQuery Ajax does not support binary responses(okay now it does), there is a trick that uses overrideMimeType('text/plain; charset=x-user-defined') to return each byte as a character in the response string and then to loop through the response to create a byte array of the data.

However with bare naked XMLHttpRequest this can be done easily with use of the responseType property.

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
    if (this.readyState == 4 && this.status == 200){
        var img = document.getElementById("CaptchaImg");
        var url = window.URL || window.webkitURL;
        img.src = url.createObjectURL(this.response);
    }
}
xhr.open('GET', 'template/bump1/purse.png');
xhr.responseType = 'blob';
xhr.send(); 
Musa
  • 96,336
  • 17
  • 118
  • 137
2

Musa's answer is a great solution, I implemented something similar in angular and works great, when you define responseType = 'blob' your response won't be a string anymore, it will be a blob type object. I just needed to add an extra parameter to the headers object (not sure if it's necessary in jQuery). headers: {'Content-Type': "image/png"}, My full request object:

var request = {
            url: "_/get_image_/get",
            method:"GET",
            headers: {'Content-Type': "image/png"},
            responseType: 'blob'
        }
Landeta
  • 21
  • 2
1

Try using new Blob(data, {type : 'image/png'}) instead of new Blob([data])

This will ensure that the media type of the blob is a png.

Source: https://developer.mozilla.org/en-US/docs/Web/API/Blob

  • I tried that, it created this png base64, but it still didn't work, the image didn't display – sneaky Aug 19 '15 at 04:10
  • @sneaky is this a response from the xhr request? – Kaiido Aug 19 '15 at 04:55
  • jquery's `ajax()` is basically a superset of browser's `XMLHttpRequest()`. But i'll guess that this is the response you got from this request to your nodejs script. Then you've got a problem since it doesn't seem to be a valid data set for an image and even less for a base64 encoded anything. – Kaiido Aug 20 '15 at 00:56
1

Whatever framework/lib you're using:

  • When getting the image (a File), ask for a BLOB type
  • Use the following function to create a Blob and get an URL out of it
  • Set your image src to that URL

Code:

export function fileToImageBase64Url(file: File): string {
  const blob = new Blob([file], { type: 'image/png' });
  return URL.createObjectURL(blob);
}

If at some point you decide that the image is not useful anymore, don't forget to clean it: URL.revokeObjectURL(yourUrl)

maxime1992
  • 22,502
  • 10
  • 80
  • 121