PHP fopen contains unwanted content - php

Of course after hours of pondering this problem, the first comment on my question lead me to solve it immediately.
The problem was that, although I was including this code within its own function at the top of the page, I was calling it only if a certain flag was set in the $_POST array. I wasn't checking for the flag until the end of the PHP file. I moved that check before the function, and it worked.
The original question is below:
I'm trying to use the fopen() function in PHP to output a CSV file, and although it contains the data I want, it also contains the entire HTML structure of the page, as well as inline stylesheets, before the content that I actually want to output.
I'm using this code (from here) pretty much unchanged. I'm very unfamiliar with PHP streaming and output, so I started from what I hope was a firm foundation:
$fileName = 'somefile.csv';
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Description: File Transfer');
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename={$fileName}");
header("Expires: 0");
header("Pragma: public");
$fh = #fopen( 'php://output', 'w' );
global $wpdb;
$query = "SELECT * FROM `{$wpdb->prefix}my_table`";
$results = $wpdb->get_results( $query, ARRAY_A );
$headerDisplayed = false;
foreach ( $results as $data ) {
// Add a header row if it hasn't been added yet
if ( !$headerDisplayed ) {
// Use the keys from $data as the titles
fputcsv($fh, array_keys($data));
$headerDisplayed = true;
}
// Put the data into the stream
fputcsv($fh, $data);
}
// Close the file
fclose($fh);
// Make sure nothing else is sent, our file is done
exit;
My assumption is that this example was intended to be included in its own external PHP file, but due to the constraints I'm dealing with, I'm trying to include it inline instead. I've mucked about with output buffering a bit with no positive results, but the PHP documentation on these is quite sparse, so there's probably something I'm missing.

Problem seems to be that, at the same time you try to output from the same PHP file, the CSV file AND some html content. You've got to separate them, to have 2 different URLs.
I guess your PHP code is surrounded by the html code (and css inline) you're talking about.
What you've got to do is:
have a PHP script that only outputs the CSV content (which only contains the code you showed us, with the opening php tag of course)
have another PHP script which produces html code, and provides a link to the previous script (for example).

You are on the right track with the 'include it inline' reason to why you're getting everything else before the data.
This script will need to be it's own separate file called directly, instead of including it inline in another script. I understand you have other database connections and such that have to be set up first. You'll have to extract those out of your standard pages and include those on this page.

Of course after hours of pondering this problem, the first comment on my question lead me to solve it immediately.
The problem was that, although I was including this code within its own function at the top of the page, I was calling it only if a certain flag was set in the $_POST array. I wasn't checking for the flag until the end of the PHP file. I moved that check before the function, and it worked.

Related

Echo out php code from file without actually executing it

We are trying to create a webpage in laravel where people are going to be able upload their codefiles to our server, so that other users can watch the code and download it in codefiles if they like it. We however can't figure out the best way to make this happen.
I tried to just let php get a file and echo out the content. this worked well fot html and css, but with php nothing got displayed what so ever. someone mentioned using eval(), however i've read that it is a really bad idea to do so. Another idea would be to stash the code in a database and fetch it from there, which we have tried before, but it sort of over complicated, and avoiding to do so would be prefereable, and instead go directly to i file.
So my question is, do anybody have an idea that might work safely, both for us and our server and for the users.
Something like this:
<?php
// read Codefile
$TheCode = file_get_contents($codefile);
// Print it...
echo htmlentities($TheCode);
?>
Save the php code in a flat file like one with a .dat extension.
then read the file.
$toechp = file(static.dat);
echo $toecho;
You can allow .dat files to be downloaded on browser using headers.
<?php
$file = "http://example.com/static.dat";
header("Content-Description: File Transfer");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$file\"");
readfile ($file);
?>
and you are done.

What does the "PK¿¿¿" response means in PHP

Hi I'm downloading a file to an app on iOS using the function readfile() on a PHP web service and I want to know if the file is downloaded correctly but I don't know how I can do that.
So what I'm trying is to do some echo to know if the file has been downloaded like this:
echo "before";
readfile($file);
echo "after";
But the response I get is this:
beforePK¿¿¿
Any one knows what does this mean or how can I know if the file is downloaded correctly?
UPDATE:
Yes it's a zip file, here are my headers
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$ticket");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
You're trying to output the contents of a zip file aren't you?
readfile($file) works the same as echo file_get_contents($file). If you're trying to present someone a file to download, do not add any additional output else you risk breaking the file.
I would also recommend reading up on the header function. That way you can explicitly tell the browser that you're sending a file, not an HTML page that has file-like contents. (See the examples involving Content-Type)
PHP should be setting the correct headers prior to readfile() - this LITERALLY reads the file out to the browser/app... but the browser/app needs to know what to do with it...
Usually you just assume that once the connection has closed that the data is done being transferred. If you want to validate that the file has been transferred fully, and without corruption you'll need to use a data structure like XML or JSON which will:
Delimit the data fields and cause the XML/JSON parser to throw an error if one is omitted, aka the transfer was cut off before it finished.
Allow you to embed more than one piece of data with the response, eg. an MD5 hash of the file that can be re-calculated client-side to verify that the data is intact.
eg:
$file = 'myfile.zip';
$my_data = array(
'file' => base64_encode(file_get_contents($file)),
'hash' => md5_file($file)
)
//header calls
header(...)
echo json_encode($my_data);
exit;

PHP writing CSV, outputting the entire webpage for some reason

function outputCSV($data) {
$outstream = fopen("php://output", 'w');
function __outputCSV(&$vals, $key, $filehandler){
fputcsv($filehandler, $vals, ',', '"');
}
array_walk($data, '__outputCSV', $outstream);
fclose($outstream);
}
function someFunctionInTheBigPHPFile() {
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=file.csv");
header("Pragma: no-cache");
header("Expires: 0");
$mydata = array(
array('data11', 'data12', 'data13'),
array('data21', 'data22', 'data23'),
array('data31', 'data32', 'data23'));
outputCSV($mydata);
exit;
}
The output CSV does contain the data array. The problem is, this array is displayed along with the rest of the webpage, that is everything before this function is called and everything that comes after it, despite these two functions being the only ones that deal with any fopen and writing to files.
How can I stop the rest of the webpage from interfering? I only want the data array in the CSV..
EDIT: I managed to chop off everything succeeding my array by adding exit;, but I still have the problem of the entire website being displayed before the array.
Stop execution after outputting the CSV data. You can do this with die() or exit().
At the beginning of the PHP file, check straight away if you want to print your CSV (this is probably passed through $_POST or $_GET). If so, run it straight through the function and end that function with an exit;.
This prevents anything from happening before or after the CSV is created. For some reason all code on the page is included in the new file, even if the file stream was opened and closed at times independant of when the page's content was computed.
And this effectively leaves you with only what you wanted, not the rubbish before or after it.
Maybe i misunderstood you, but someFunctionInTheBigPHPFile() prints out the file to the screen. So, why are you using this i you dont want to a screen output ?

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.

send a file to client

I want to write a text file in the server through Php, and have the client to download that file.
How would i do that?
Essentially the client should be able to download the file from the server.
This is the best way to do it, supposing you don't want the user to see the real URL of the file.
<?php
$filename="download.txt";
header("Content-disposition: attachment;filename=$filename");
readfile($filename);
?>
Additionally, you could protect your files with mod_access.
In addition to the data already posted, there is a header you might want to try.
Its only a suggestion to how its meant to be handled, and the user agent can chose to ignore it, and simply display the file in the window if it knows how:
<?php
header('Content-Type: text/plain'); # its a text file
header('Content-Disposition: attachment'); # hit to trigger external mechanisms instead of inbuilt
See Rfc2183 for more on the Content-Disposition header.
PHP has a number of very simplistic, C-like functions for writing to files. Here is an easy example:
<?php
// first parameter is the filename
//second parameter is the modifier: r=read, w=write, a=append
$handle = fopen("logs/thisFile.txt", "w");
$myContent = "This is my awesome string!";
// actually write the file contents
fwrite($handle, $myContent);
// close the file pointer
fclose($handle);
?>
It's a very basic example, but you can find more references to this sort of operation here:
PHP fopen
If you set the content type to application/octet-stream, the browser will ALWAYS offer file as a download, and will never attempt to display it internally, no matter what type of file it is.
<?php
filename="download.txt";
header("Content-type: application/octet-stream");
header("Content-disposition: attachment;filename=$filename");
// output file content here
?>
Just post a link on the site to http://example.com/textfile.php
And in that PHP file you put the following code:
<?php
header('Content-Type: text/plain');
print "The output text";
?>
That way you can create the content dynamic (from a database)...
Try to Google to oter "Content-Type" if this one is not the one you are looking for.

Categories