Line feed in output buffer after dispatch - php

Using the Zend Framework, I wanted to send a file.
But when doing so from my controller I noticed a LineFeed allready sent:
The following code:
$data = 'Let me test this';
header('Content-Type: text/plain');
header('Content-Disposition: attachment; filename="output.txt";' );
//header('Content-Length: '.strlen($data));
ob_clean(); flush();
die($data);
Will give me the output.txt file:
[LF]
Let me test this
I have a preDispatch plugin, but I tried with the test code before exiting it, and the LF wasn't outputted yet. And all controller-files starts with <?php. without any LF first.
So, my question is:
What happens between preDispatch plugins are run and the controller is dispatched?
.. or even better: How can I find out where the LineFeed is outputted?

I have tested your code with an empty preDispatch() method in a Zend_Controller_Plugin_Abstract derived plugin, and I don't get any LF in the output. I do get it, however, if I add echo "\n" explicitly into the preDispatch() method body.
So, chances are that your plugin is outputting the LF somewhere else. Maybe you are using a closing tag in your plugin? (just to discard possibilities).
For files that contain only PHP code, the closing tag ("?>") is never
permitted. It is not required by PHP, and omitting it´ prevents the
accidental injection of trailing white space into the response.
(in the Zend Framework Coding Standard)

Related

PHP - Download file(s) from the server without revealing the URL - A few GOTCHAS

I am working on a "simple" shopping cart app that allows users to purchase downloadable products. I am interested in creating a link to a digital product without revealing the full URL to the end user. I have searched other solutions here and understand the basics of making a "download.php" file that references the product ID, stored as a HASH type value in the DB, that can then be referenced to get the actual URL of the file.
However, there are some formatting issues that I've bumped into that others might find interesting:
The following link is an example: Download files from server php
It shows the following code as the headers of the downloadable document (Referencing a PHP variable):
header("Content-Disposition: attachment; filename=$file");
Another example of that is here: Start a download with PHP without revealing file URL
readfile($file);
However, if you look at the PHP HEADERS documentation here: PHP - HEADERS Documentation
You'll notice that all of the arguments passed are wrapped in single quotes:
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="downloaded.pdf"');
readfile('original.pdf');
Those who are particularly gifted in attention to detail will also notice that the Content-Disposition argument has the filename wrapped in double quotes . . . with the full argument wrapped in single quotes.
If I followed the code in the above examples (leaving out the single and/or double quotes) the file seems to be corrupted, missing, or just fails to load. So how do I fix this?
To get this working in my own code, I needed to wrap my PHP variables in either single or double quotes (and sometimes doubled single quotes) as shown below:
header('Content-Type:'.$ctype.'' );
header('Content-Disposition: attachment; filename="'.$fname.'"');
readfile(''.$filepath.'');
When entered this way, I was able to download the files without corruption or issue. Please let me know if you are aware of a better way of doing this.
However, when I used the coded above it also allowed me to NOT use the
ob_clean();
ob_end_flush();
commands in my code. In fact if I add them now . . . it seems to corrupt my files too. Weird.
Another potential GOTCHA is that if you attempt to download a TXT file, and you have a PHP "echo" statement anywhere in your "download.php" file, the contents of the ECHO statement will be appended to the TXTY file that's downloaded. So just something to be careful of.
This ECHO statement may also be appended to the headers of other documents types as well, but it didn't seem to affect the ability of the file to open in my limited testing. But again, be careful out there! :)

Downloading file from server PHP - File is slightly off

I hope this is a simple and quick fix. I have looked on here already to learn how to force download a file from the server. Here is what I am using below:
<?php
// Sending the file - a pdf in this case
header('Content-type: application/octet-stream');
// Specify what the file will be called
header('Content-Disposition: attachment; filename="1234.txt"');
// And specify where it is coming from
readfile('C:\test\1234.txt');
?>
It should be pretty self explanatory but I have a text file saved at C:\test\1234.txt.
I link to my php file (that has the above code) which is called download.php using this from the HTML page:
Download This File!
OK now the problem.. My original text file is this:
test
but when I download the file, the result is a carriage return above:
_
test
The problem isn't huge with the text file, but because of this issue, all other files downloaded are corrupt and I believe this is why. I am hoping that someone has a solution to this that is pretty simple.
Thanks in advance!
You might try removing the PHP closing tag. Note this quote from php.net
If a file is pure PHP code, it is preferable to omit the PHP closing
tag at the end of the file. This prevents accidental whitespace or new
lines being added after the PHP closing tag, which may cause unwanted
effects because PHP will start output buffering when there is no
intention from the programmer to send any output at that point in the
script.
Perhaps that's where you're getting the extra carriage return.

PHP MVC Framework + Generate KML file

I implemented a basic mvc framework in php. The problem is that when I want to create a dynamic kml file not open, because the file at the start of blank spaces are generated. If I do it from any file (not the framework), it works correctly.
Link :localhost/Radio/index/asset
Controller : indexController.php
method : asset()
code:
public function asset() {
$dom = new DOMDocument('1.0', 'UTF-8');
$kmlOutput = $dom->saveXML();
$kmlOutput = trim($kmlOutput);
header('Content-type: application/vnd.google-earth.kml+xml');
header('Content-disposition: attachment; filename="myfilename.kml"');
echo $kmlOutput;
}
error in Google Earth :
kml generate:
Thanks in advance.
Blanks at the beginning of the output are often caused by newlines behind the closing php tag.
<?php¶
¶
// Some code here¶
¶
?>¶
¶
Anything outside of <?php ?> as directly seen as output. Therefor, you should never use the closing tag in library files.
To quote Zend Framework:
For files that contain only PHP code, the closing tag ("?>") is never
permitted. It is not required by PHP, and omitting it´ prevents the
accidental injection of trailing white space into the response.

DOMPDF: Unable to stream pdf: headers already sent

I am generating php page using smarty template based on html form input and uploaded files. Using dompdf, I want to save the generated page as a pdf file.
When the user submits the multipart/form-data, data is posted to itself. Then it undergoes validation process. When all is fine, a new page is generated using a template file. There is no output, instead, dompdf utilizes the template file to stream the pdf file. After solving several stages of problems such as "DOMPDF not found", insufficient memory etc, I am now stuck with "Unable to stream pdf: headers already sent" error.
One of the most common problems is presence of line break, white space or any output being before stream() is called. I checked for white space before and after <?php and >?.
There are nor print_f or echo statements either. How can I troubleshoot this problem? Where does the problem lie...in the smarty template file or the php file itself?
Here is the code:
require_once("dompdf/dompdf_config.inc.php");
spl_autoload_register('DOMPDF_autoload');
$html = $smarty->fetch('index.tpl');
$dompdf = new DOMPDF();
$dompdf->load_html($html);
$dompdf->set_paper('a4', 'portrait');
$dompdf->render();
$dompdf->stream("newfile.pdf");
simple solution :
write below lines before stream, it will show where exactly new line or space is coming
$f;
$l;
if(headers_sent($f,$l))
{
echo $f,'<br/>',$l,'<br/>';
die('now detect line');
}
I had the same problem, and I solved this problem by adding this code in the top file:
ob_start();
Most probably there's a whitespace or new line somewhere in your code causing this. Here's a simple way to debug it:
echo something at the very end of your script (above the stream() call), for example echo "end!";exit;
Click to "view source" of your page, which makes spaces easier to see
If your "end!" string does not appear at the very start of your script, then somewhere there's a character printed
Move the "echo end!" line further up to your code, until you locate where the space was inserted
Another possibility is that you are using a language string somewhere that introduces an unprintable character. If your application is multilingual, make sure you're testing using english
Replace line 3105 of this file: dompdf/lib/class.pdf.php
if ( headers_sent()) {
die("Unable to stream pdf: headers already sent");
}
With
$output = ob_get_clean();
if ( headers_sent()) {
echo $output; }
Then in the file that is generating the pdf output e.g if you were outputting from a Joomla Component
components/com_joomlacomponent/views/yourpdfdir/tmpl/default.php
Enter immediately after the opening php tag
<?php
ob_start();
I tried to echo out, but no white spaces or line breaks were found. At the end, I redirected the php to another page instead of PHP_SELF and the problem vanished. I did not alter any code. Looks like presence of html tags after the php ended was the offending factor.
Be sure your editor does not add a Unicode Bom description - save code to file by Notepad, or (if you work in Dreamweaver) remove check by Asign Unicode Signature (BOM) or something. ;)
I came across this issue. You want to check all the variables you are using.
One or even more than one variable you are passing comes empty and is messing the render.
Start gradually, by getting rid of all the php and try to generate the pdf, then if it works for you add code block by block.
This will help you identify where the problem is.
I had this issue, with no apparent output when viewing the source. The problem for me was that I had flushed the output, even though there was none except the headers, and that blocked streaming the output giving the "headers already sent" message. Which was true. My fix was to remove the flush() and ob_flush() statements, and the streaming output then worked.
for me - solution was to encode my file to UTF-8 instead of UTF-8 BOM
In my case the problem was solved by setting $_dompdf_show_warnings to false in dompdf_config_inc.php

How to stop PHP prefixing LF to start of file

I am using PHP to pass some information in a text file back to the user which is then used as input for an app. I'm using the method shown in the following snippet to serve the file to the user.
header('Content-type: text/csv');
header('Content-Disposition: attachment; filename=filename.dat');
echo $data;
exit();
I get the save as dialogue fine and the data is present the only problem is that there is a line feed character at the start of the output file which I cant seem to get rid of.
It just so happens that the app that uses the data is sensitive to white space and although it would be easy to fix this, forcing the users to update is not a route I want to go down for various reasons.
Does anyone know what is causing this and more importantly any workarounds.
As I already said in the comments to the question:
Either you $data contains that line feed or there is something before that snippet that does this. Maybe a line feed before you opened the PHP block.
Probably $data contains the line feed.
Look for includes too
Presumably the extra newline is getting into $data somehow. If you can’t fix that, you could trim() the data before you echo it.
Can you post how you're setting $data?
Just an additional note.
In case you are working on a project where you cannot identify the files that have the leading or trailing line feeds, new lines, carriage returns just call the code below before your headers:
//Loop through any open buffers and nuke them.
while(#ob_end_clean());
header('Content-type: text/csv');
header('Content-Disposition: attachment; filename=filename.dat');
echo $data;
exit();
This may have some unexpected side-effects on the code that relies on those buffers but is an effective way to completely clear out your output buffer.
Maybe you can use ob_get_contents or ob_get_length to see if anything has been sent to the output before the echo statement. Or use ob_clean before the echo.

Categories