-2

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();
?>
Palec
  • 12,743
  • 8
  • 69
  • 138
Kraishan
  • 443
  • 5
  • 14
  • 38
  • Fixed the }... Must've missed that somewhere. Now the page gives me the error 404 not found. The image URL was not found on the server. – Kraishan Dec 05 '13 at 19:10
  • You are doing `echo $output;` while still in the output buffer. Try echoing at the very end. Also, I think you want `ob_end_clean` instead of `ob_end_flush`. – gen_Eric Dec 05 '13 at 19:11
  • Edited the post. Still not working, output it echoed at the very end. – Kraishan Dec 05 '13 at 19:15
  • Actually... why are you using output buffering at all here? Why not just let `imagepng` echo to the screen for you? – gen_Eric Dec 05 '13 at 19:17
  • 3
    This question appears to be off-topic because it is unlikely to help anyone in the future – Mike B Dec 05 '13 at 19:18
  • Because if I don't use this buffering system at all, I will get a header error. – Kraishan Dec 05 '13 at 19:18
  • @user2014780 And that's why output buffering is a cover-up/bandaid fix for header errors. Hooray for exposing bad design. – Mike B Dec 05 '13 at 19:19
  • Well, neither using a direct echoing of imagePNG or the output buffering works for me :P – Kraishan Dec 05 '13 at 19:26
  • It still doesn't work, even though I have done everything you good fellows proposed :( – Kraishan Dec 07 '13 at 14:08

5 Answers5

2

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
Marc B
  • 356,200
  • 43
  • 426
  • 500
  • That's not in my PHP script, must have gone wrong when indenting it on stack overflow. – Kraishan Dec 05 '13 at 18:58
  • 2
    this is probably the correct answer. wrap everything in one single all the spaces in between those are included in your output buffering. – Octopus Dec 05 '13 at 19:00
2

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.

Palec
  • 12,743
  • 8
  • 69
  • 138
  • Thanks for your help, and sorry for the late reply. I finally got rid of the header errors. But it now produced some more: Warning: imagecreatetruecolor() [function.imagecreatetruecolor]: Invalid image dimensions in afbeelding-snijden.php on line 22 Warning: imagecopyresampled(): supplied argument is not a valid Image resource in afbeelding-snijden.php on line 25 Warning: imagejpeg(): supplied argument is not a valid Image resource in afbeelding-snijden.php on line 27 – Kraishan Jan 05 '14 at 08:39
  • @user2014780 That is quite clear. At both places where `imagecreatetruecolor` is used, its arguments are taken from `$_POST`. If you provide bad arguments, it refuses to work. Bad arguments include empty strings, nulls etc. The other two errors are just consequences of the image not having been created. Be sure to provide integers in `$_POST['h']` and `$_POST['w']` and everything should work OK if you made the fixes I proposed. – Palec Jan 05 '14 at 23:24
1

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.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
  • he was doing ob_get_contents before that last ob_end_clean. – Octopus Dec 05 '13 at 19:04
  • @Octopus Thanks for your reply. I did. Did you read my last paragraph? – GolezTrol Dec 05 '13 at 19:05
  • thats true, he doesn't echo $output. but i didnt down vote you :) – Octopus Dec 05 '13 at 19:06
  • I should hope so. ;-) – GolezTrol Dec 05 '13 at 19:07
  • 1
    perfectly correct, "echo $output" before "ob_end_clean" essentially does nothing because output of echo is stored in buffer and then discarded by ob_end_clean. But really the whole use of output buffering is wrong here, this code should be rewritten not to use output buffering at all. – leofonic Dec 13 '13 at 12:05
0

update ur code like this:

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

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

towser
  • 1
  • 1
0

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.

leofonic
  • 331
  • 1
  • 3