phpjqueryajaxbinaryx-sendfile

PHP - return image with header("X-sendfile") returns null on first iteration, binary on second (using ajax)


Okay. I have a gallery-app I'm building, where I have a list of thumbnails, and when clicked, fetches the original image via an ajax-call to a showfile.php which just returns the file via header() using X-Sendfile. This works, but for some reason I can't get a subsequent call to return the correct values, and the script breaks. (First return returns "null", which is what I want, while second returns the image as binary data).

Okay. Here's the code for the ajax-call:

$('.lightbox').click(function(e) {
e.preventDefault();
var $this = $(this);
var linkName = $(this).attr('href').split('=')[1];
$.ajax({
  url: 'showfile.php',
  type: 'GET',
  dataType: 'binary',
  data: 'file='+linkName+'',
  responseType: 'blob',
  processData: false,
  success: function(result) {
    var image = new Image();
    image.src = URL.createObjectURL(result);
    $('#lightbox_container').append(image).removeClass('hidden').addClass('visible');
    image.onload = function() { var imageWidth = image.width/2; $('#lightbox_container').css({'margin-left':'-'+imageWidth+'px'}); window.URL.revokeObjectURL(image.src);};
    $('#overlay').removeClass('hidden').addClass('visible');
    $('.nextbutton,.prevbutton').click(function(e) {
        if ($(e.target).hasClass('prevbutton')) {
            var linkName = $this.parent('.pictures').prev('li.pictures').find('a').attr('href').split('=')[1];
            $.ajax({
                url: 'showfile.php',
                type: 'GET',
                datatype: 'binary',
                data: 'file='+linkName+'',
                responseType: 'blob',
                processData: false,
                success: function(result2) {
                    var image = new Image();
                    var binaryData = [];
                    binaryData.push(result2);
                    image.src = URL.createObjectURL(new Blob(binaryData));
                    // image.src = URL.createObjectURL(result2);
                    $('#lightbox_container img').remove();
                    $('#lightbox_container').append(image);
                    image.onload = function() { var imageWidth = image.width/2; $('#lightbox_container').css({'margin-left':'-'+imageWidth+'px'}); };
                }
            })
        }
    })
  }
}); 
});

This works, up until the second ajax-call - the return value from showfile.php on the second call is a binary block (if I look at the NET-tab in console, I get the correct image returned), but for some reason the createObjectUrl doesn't work (I've tried without the binaryData-bit, but then the createObjectUrl just fails, naturally, since the result isn't correct for the usage.

The showfile.php is as follows:

<?php
require_once('conf/config.php');
if (!session_id()) { session_start(); };
if ($isloggedin) {
    if (isset($_GET['file'])) {
        // $getFile = readfile($_SERVER['DOCUMENT_ROOT'].'/'.$userpath.$username.'pictures/'.$_GET['file']);
        header('Content-type: image/jpeg');
        header('X-Sendfile: '.$_SERVER['DOCUMENT_ROOT'].'/'.$userpath.$username.'pictures/'.$_GET['file'].''); # make sure $file is the full path, not relative
        exit;
        // echo base64_encode($getFile);
    }
}
?>

There are some commented lines, I was trying using readfile() instead, doesn't work any better, just seems a bit slower in general.

So, what I'm after is: what am I doing wrong? As the ajax-call works on first click, it should work on second click as well, right? But it doesn't. However, if I close the image down, and click a new thumbnail, it works just fine. No refresh of the page or anything like that, just close the popup, and click a new thumbnail, it works again. But for some reason, it doesn't return the same "null" value on second click.

Which leads me to believe that there is something not being closed or reset or whatever, and some sort of "left over" issue - which leads me to the php-file, since that is what seems to return different values. Is there anything there I can do to "zero out"?

I've tried Googling, but haven't really found that much information about these functions at all.

Oh, the second ajax-click returns, as I said, some binary information - but when I try to create an objectUrl from it, using blob, it doesn't work - ie, the url doesn't work, it just shows a broken image icon, not the actual image, although the url seems correct (same url as if I revisit the thumbnails and click again, starting over), and as I said, the net-tab in console shows the image being returned in both cases.


Solution

  • Okay, I feel incredibly stupid now. It's a typo. The datatype should be dataType- sometimes the camel-case in javascript trips me up. Changing that fixes the issue.