21

I need to send a base64 encoded string to a client. Therefore, I'm opening and reading an image file on the server, encode it and send that data along with the image/jpeg content-type to the browser. Example in php:

$image      = $imagedir . 'example.jpg';
$image_file = fopen($image, 'r');
$image_data = fread($image_file, filesize($image));

header("Content-type: image/jpeg");
echo 'data:image/jpeg;base64,' . base64_encode($image_data);

Clientside, I'm calling:

var img     = new Image();
img.src     = "http://www.myserver.com/generate.php";
img.onerror = function(){alert('error');}
$(img).appendTo(document.body);

That does not work for some reason. onerror always fires. Watching the FireBug Network task for instance, tells me that I'm receiving the correct header information and a correct value of transfered bytes.

If I send that data as Content-type: text/plain it works, the base64 string is shown in the browser (if I call the script directly). Copying and pasting that output into the src of a <img> element shows the image as expected.

What am I doing wrong here?

Solution

Thanks Pekka for pointing me on my mistake. You don't need (you can't!) encode that binary image data as base64 string in that kind of approach. Without base64 encoding, it just works.

jAndy
  • 231,737
  • 57
  • 305
  • 359
  • Looks like you should be setting the `src` attribute's value to the response text directly (i.e. `img.src = "data:image/jpeg;base64,..."`... and the right-hand side here could be a return value from an Ajax call) - otherwise the browser will try to request an image from the URL you're setting it to, which won't work because it's returning `data:image...` instead of the image bytes directly. – John Rasch Jul 15 '10 at 20:58
  • I don't want the overhead of an `ajax call`. I need it as quick as even possible. To get somekind of a 'response' I need a valid image to check for a width for instance. – jAndy Jul 15 '10 at 21:05

4 Answers4

14

If you set content-type to image/jpeg, you should give just the jpeg data, without the base64 crap. But you're treating the result as if it was html.

You're effectively building a data uri, which is ok, but as you noted, only as an uri. So leave the content type as it is (text/html), and

echo '<img src="data:image/jpeg;base64,'.base64_encode($image_data).'">';

and you're good to go.

mvds
  • 45,755
  • 8
  • 102
  • 111
5

I believe it can be done quite efficiently just using php only ... you can use the below function to render images in base64 encoded data

    function binaryImages($imgSrc,$width = null,$height = null){
    $img_src = $imgSrc;
    $imgbinary = fread(fopen($img_src, "r"), filesize($img_src));
    $img_str = base64_encode($imgbinary);

    if(isset($height) && isset($width))
    {
    echo '<img src="data:image/jpg;base64,'.$img_str.'" height="'.$height.'" width="'.$width.'"/>';
    }
    else
    {
    echo '<img src="data:image/jpg;base64,'.$img_str.'"/>';
    }
}

how to use this function

    binaryImages("../images/end.jpg",100,100); 

run the function binaryImages .. 1st parameter is the image path , 2nd is the width and then the height ... height and width are optional

Aman Virk
  • 3,909
  • 8
  • 40
  • 51
  • this is a good approach if some 1 wants image with different resolutions.This will also hide image url? if it does then it is also better if some 1 is willing to hide image URL – noobie-php Nov 12 '15 at 07:41
3

In this case, there is no reason to base64 encode the image data in the first place. What you want to emit is plain old image data.

Just pass through the JPEG image as-is.

The only way this would make sense to me is if you grabbed the output of generate.php via an AJAX call, and put the result into the src property directly. That should work (although not in IE < 8, but I'm sure you know that). But if you can call generate.php directly as the image's source, I don't see the need for this.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • @Pekka: I'm writting a beacon. I need somekind of response to the client, I'm looking for checking the image width to get different response types. I'm doing this because I don't **want** the overhead of an `ajax call`. – jAndy Jul 15 '10 at 21:03
  • @jAndy that should work fine with a normal `src` property, no need to base64 encode anything I think. **Re your update:** you could also determine the image width on server side, and send that through as an integer (instead of the whole image). You'd need to make a proper Ajax call for that, though. – Pekka Jul 15 '10 at 21:04
  • @Pekka: I'm afraid I don't get you? How would I send an image through a server script file to the client without encoding it with bas64 ? – jAndy Jul 15 '10 at 21:06
  • @Pekka: The idea is to call a server script within a `` src, which just works fine (that's a beacon). Pretty fast, way faster than an `ajax call`. But the dark side here is not getting a server response properly. So my idea was to do it with sending back different images. Success could be 2pixel width, error 1 pixel and so forth. – jAndy Jul 15 '10 at 21:09
  • 2
    @jAndy aaah, I see! Interesting. But either you or me are misunderstanding something: If you set an image's `src` to some server-side script, the stuff that script needs to emit is *not* base64 encoded. Just plain image data. Or am I getting something wrong? – Pekka Jul 15 '10 at 21:11
  • @Pekka: OMG, I LOVE YOU :p That was my only mistake here. For some reason I thought, "no you can't send binary data like that", but OF COURSE I can!!. Works now, woohhooo :) – jAndy Jul 15 '10 at 21:14
  • All right! :) And this is an interesting way to do beacons, wasn't aware setting a src was faster than Ajax. Nice! – Pekka Jul 15 '10 at 21:17
  • 1
    "Why are you base64 encoding the image data at all." This is not very helpful. I'm building an API for a client that demands base64 image content to be sent. To test that things are working right, I needed to create an tag and use this data. +1 @mvds for a quick and straightforward answer. (edit) although after reading the comments, it does sound like he didn't need to encode it. But, the question was, how to display encoded data, and that's the question I needed answered. – Dustin Graham Nov 16 '12 at 22:22
0

i would recommend it: base64_encode Encodes data with MIME base64

echo '<img src="data:image/jpeg;base64,'.base64_encode($image).'">';
Mahbub Alam
  • 368
  • 2
  • 6