Image not showing ob_start() - php

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();
?>

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

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.

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.

update ur code like this:
......
switch($ext)
{
case 'jpg';
ob_start();
......
cannot have output before header().
aha, my English sucks.

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.

Related

Output image to browser AND write to disk

This seems like a SUPER easy question for people who knows PHP but I can't figure out how to make this work (probably because I know VERY little about PHP). Most question related to this asks how to output an image to either browser or disk, but I wanna do both. See example below:
<?php
header('Content-type: image/png');
$filename = "my_written_image.png";
$png_image = imagecreatefrompng('some_fancy_image.png');
imagepng($png_image, $filename);
imagepng($png_image);
?>
This won't work. The image won't show in the browser, but it will work if I remove this line: imagepng($png_image, $filename);
I'm guessing one can only "output" one thing using imagepng but how will I accomplish the above?
You should use the following code:
<?php
header('Content-type: image/png');
$filename = "my_written_image.png";
$png_image = imagecreatefrompng('some_fancy_image.png');
file_put_contents($filename, $image);
imagepng($png_image, $filename);
?>
My server is not turned on so I can't test the code but I think this should work.
Okay it seems my original solution actually did work. The problem was I was using (in my real code): if(readfile("myfile.png")) and this will return false if it's not found, but it will also throw an error if #readfile() is not used (note the #). The docs said:
an error message is printed
I didn't think this would cause the whole thing to fail. Sorry for my stupidness.

One command to get output buffer and erase it in PHP?

Is there any command to get the output and erase the buffer without turning it off?
eg.
ob_start();
include 'first_page.php';
$first_page = ob_get_clean();
ob_start();
include 'second_page.php';
$second_page = ob_get_clean();
ob_start();
....
Is there a function available so I don't have to turn on output buffering every time?
I know this is an old question but I was looking for an answer to this question and wanted to post the answer based on comments posted here.
It looks like the answer is no, there is no single command to get the output buffer and erase it without turning it off. However, instead of repeatedly starting a new buffer, you could just erase the current buffer with ob_clean() in between calls of ob_get_contents()
For example:
ob_start();
include 'first_page.php';
$first_page = ob_get_contents();
ob_clean();
include 'second_page.php';
$second_page = ob_get_contents();
ob_end_clean();

PHP output buffer issue when using ob_gzhandler and ob_clean together

I'm having a hard time figuring out the problem in the following code, I really need a solution to this.
Consider the following code :
<?php
//starting a new output buffer, with a GZIP compression
ob_start("ob_gzhandler");
//this goes into the buffer
echo "Hi";
//grabbing the buffer's content
$content = ob_get_contents();
//cleaning the buffer
ob_clean();
//we're still inside the buffer, show the content again
echo $content;
This code fails to output "Hi", instead I see "‹óÈM", what have done that broke correct buffering? Knowing that once I remove "ob_gzhandler", the buffering is correct and everything is fine. I don't want to create another buffer and destroy the current one. I just want to clean the current one using ob_clean.
Any ideas? Thanks in advance.
Thank you for your answer, I figured out why, GZIP is insalled on my machine by the way, it's that when setting ob_gzhandler, the buffer is compressed chunk by chunk, so when using ob_get_contents(), parts of the last chunck are missing, and I end up getting weird output.
To correct that behaviour (or at least to bypass it), open a second output buffer, and leave the one with gzhandler() alone.
Like this
ob_start("ob_gzhandler");
ob_start();
Now the second one isn't compressed, I can do whatever I want with it (hence get its content, clean it etc). The content will be compressed anyway given that a higher level output buffer with gzhandler is opened.
Maybe you don't have gzip compression enabled/installed on your machine.
Tried your code and got something like that. I don't have gzip installed on my machine, try this:
It's your code but with a condition, if gzip doesn't start, the buffer starts.
//starting a new output buffer, with a GZIP compression
if (!ob_start("ob_gzhandler")) ob_start();
//this goes into the buffer
echo "Hi";
//grabbing the buffer's content
$content = ob_get_contents();
//cleaning the buffer
ob_clean();
//we're still inside the buffer, show the content again
echo "<pre>"; echo $content; echo "</pre>";
ob_end_flush();
If you get "Hi", maybe gzip is not installed.

Any difference between print() and readfile() when loading an image file?

Just wondering if there is any difference with the two below code examples:
$image = 'http://www.example.com/image.jpg'
$photo = file_get_contents($image);
ob_start();
header("Content-type: image/jpeg");
print($photo);
ob_end_flush();
or...
$image = 'http://www.example.com/image.jpg'
$photo = file_get_contents($image);
ob_start();
header("Content-type: image/jpeg");
readfile($photo);
ob_end_flush();
readfile's parameter is a filename, not the content itself. Therefore, you'd call it like this:
$image = 'http://www.example.com/image.jpg'
ob_start();
header("Content-type: image/jpeg");
readfile($image);
ob_end_flush();
Since readfile reads and write chunks at a time, its memory consumption will be constant, whereas when you store the result of file_get_contents into $photo, you'll need to have enough memory to store the image.
In your case, the output buffering makes the file_get_contents variant demand twice as much memory as the image's size. For a large image, readfile therefore halves the memory requirements. Note that your output buffering means that the download will be delayed. If you don't need it for anything else, you will get better performance (both in actual speed and server memory requirements) if you simply disable it:
$image = 'http://www.example.com/image.jpg'
header("Content-type: image/jpeg");
if (#readfile($image) === false) {
// print error image
}
There is a very significant difference in that readfile takes the filename as the argument.
The second snippet should be something like
$image = ...
readfile($image)
This has the advantage of not having to store the entire file contents in memory (a string) since readfile emits it immediately. Of course, if you buffer the output that is no longer true.
In the first instance your code would never work
readfile($photo);
^--------------- Takes file name not string
PHP DOC SAYS
Reads a file and writes it to the output buffer.
You don't need to re event that and duplicate that with multiple other functions its just saying
readfile = file_get_contents + print
It just like using fopen instead of file_get_contents just a get a simple content in a file
Lastly readfile is faster tested with 10000 loop on same image
Single Run
Array
(
[m1] => 0.0006101131439209
[m2] => 0.00031208992004395
)
Dual Run
Array
(
[m1] => 3.4585757255554
[m2] => 2.9963381290436 <---- Faster
)
m1 & m2 functions
function m1($array) {
$photo = file_get_contents('a.png');
ob_start();
print($photo);
ob_end_clean();
}
// Array clean copy
function m2($array) {
ob_start();
readfile('a.png');
ob_end_clean();
}

How to save a search Query (Copying the file and Saving )

I want to copy the file http://searchr.us/Testing/web-search.phtml?search=SEARCHED+TEXT to
http://searchr.us/Testing/search/SEARCHED+TEXT.html
How do i do this?
NOTE:The source of http://searchr.us/Testing/search/SEARCHED+TEXT.html should be the same as http://searchr.us/Testing/web-search.phtml?search=SEARCHED+TEXT
Indirectly I'm just saving a query so that I can keep a track of them!
Hope i've get you right: you want to store output of any query into file. You can manage this with output buffering.
In the begining of script wright:
ob_start(); // start buffering
This turns buffering on.
At the eng of page wright something like this ($query is text of query):
$html = ob_get_contents();
ob_end_flush(); // this turns off buffering and sends buffered content to output
$fp = fopen("{$query}.html","w");
fwrite($fp,$html);
fclose($fp);

Categories