Image not showing ob_start()

2.3k views Asked by At

Couldn’t find anything on the webs so here is the issue: I have a cropper tool and I want to show the cropped image on this page. But because my functions.php has a function that uses a header method, I had to use ob_start in my file. That causes the problem that my image is not shown (it’s a question mark right now, not the right image).

Code:

<?php
ob_start();
require_once("includes/session.php");
require_once("includes/connection.php");
require("includes/constants.php");
require_once("includes/functions.php");
confirm_logged_in();
require_once("includes/header.php");

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $targ_w = $_POST['w'];
    $targ_h = $_POST['h'];
    $jpeg_quality = 90;
    $src = $_POST['image'];
    $ext = end(explode(".", $_POST['image']));
    switch($ext) {
        case 'jpg';
            $img_r = imagecreatefromjpeg($src);
            $dst_r = imagecreatetruecolor($targ_w, $targ_h);

            imagecopyresampled($dst_r,$img_r,0,0,$_POST['x'],$_POST['y'],
                $targ_w,$targ_h,$_POST['w'],$_POST['h']);
            header('Content-type: image/jpeg');
            imagejpeg($dst_r,null, $jpeg_quality);
            $output = ob_get_contents();
        break;
        case 'png';
            $img_r = imagecreatefrompng($src);
            $dst_r = ImageCreateTrueColor($targ_w, $targ_h);
            imagecopyresampled($dst_r,$img_r,0,0,$_POST['x'],$_POST['y'],
                $targ_w,$targ_h,$_POST['w'],$_POST['h']);
            header('Content-type: image/png');
            imagepng($dst_r, null, 8);
            $output = ob_get_contents();
        break;
    }
}
echo $output;
ob_end_clean();
?>
5

There are 5 answers

5
GolezTrol On

ob_start starts output buffering. ob_end_clean cleans the buffer and stops output buffering without sending anything to the client, so you basically discard any output.

I think you meant to use ob_end_flush instead of ob_end_clean, which sends the output buffer to the client instead of just ending buffering.

Since you used ob_get_contents to put the output in a variable, you could opt to echo that variable after calling ob_end_clean, but that will make your script just larger, less clear and more memory-consuming, since you then have the contents of the entire image in the output buffer and in the $output variable. So I think using ob_end_flush really is the better option.

2
Marc B On

Given how your code is indendent:

    <?php ob_start(); ?>
    <?php require_once("includes/session.php"); ?>
    [...snip...]
$targ_h = $_POST['h'];

Those 4 spaces before the <?php ob_start call are output and disabling your subsequent header() calls.

Plus, nowhere do you actually OUTPUT your image data:

  $output = ob_get_contents();
  echo $output; // <----you need this
2
Palec On

When outputting binary files, make sure you output only the data you want to:

  • The first thing in your code should be <?php and you should never leave the PHP code. No ?> should be used, more below.
  • When using Unicode in your script, be sure not to include BOM.
  • Do not use the closing ?>. It is not necessary. If you use it, anything after that is sent to output. This includes a newline character at the end of the last line of the script.
  • If your code is designed poorly and generates any garbage before outputting the data, buffer the garbage generation and then throw away the buffer just before outputting the data.

Now to your code specifically:

  • In switch statement, the case part is ended by a colon, not semicolon. I.e. write case 'jpg': instead of case 'jpg';.
  • The ob_end_clean(); at the end of your script should be moved right after the last require_once call. The includes are producing garbage, the rest of the output is wanted; therefore you should buffer only the output generated by the includes and then throw the buffer away and let the rest be unbuffered.
  • Delete the lines $output = ob_get_contents(); (occurs twice) and echo $output;. After performing the previous change, they are not needed anymore, they just produce errors.

Try it and see if it helps. If not, comment on this answer and we’ll try to find your problem.

0
leofonic On

But because my functions.php has a function that uses a header method, I had to use ob_start in my file. That causes the problem that my image is not shown (it’s a question mark right now, not the right image).

Both statements are not really true. First: if you have a function that uses a header method, don't worry, as long as the function is not executed, your script doesn't care about the header method. And if it gets executed, ob_start wont help, because

While output buffering is active no output is sent from the script (other than headers), instead the output is stored in an internal buffer.

(http://www.php.net/ob_start) Note the "other than headers". So the real problem is not you have a header method, but that you have some output in one of your includes, either a whitespace or any other output, e.g. "includes/header.php" sounds like it may output the html header.

So first thing would be to remove all output from these files, and then remove all output buffering functions from your script.

So really you don't need output buffering, but even if you would need it, output buffering is not the cause that your image is not shown, output buffering works fine, but in your code you output the image before ob_end_clean, thus discarding any output.

And if you really by no means can remove the output from the includes, just call ob_end_clean right after the includes and continue as usual without output buffering.

0
towser On

update ur code like this:

......
switch($ext)
  {
      case 'jpg';
      ob_start();
      ......

cannot have output before header(). aha, my English sucks.