Forcing generated CSV to download when run as cron on server - php

I'm trying to get an export to CSV script to download to the server when run as a cronjob but also still work via web.
When I run the script from web it forces a CSV to download which is great, however when I run it on the server (CentOS Server) it just echos the file contents instead.
I need it to download the file into the area defined in the cronjob.
//OK lets export
include("config.php");
$table = "data";
$filename = "Export_" . date("Y-m-d_H-i");
header("Content-type: text/csv; charset=UTF-8");
header("Content-Disposition: attachment; filename=" . $filename . ".csv");
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// output the column headings
fputcsv($output, array('artist', 'title', 'presenter', 'timeplayed'));
// fetch the data
mysql_connect($dbhost,$dbuser,$dbpass);
mysql_select_db('prs');
$rows = mysql_query('SELECT * FROM '.$table.' WHERE timeplayed >= NOW() - INTERVAL 24 HOUR ORDER BY id DESC');
if($rows === FALSE)
{
die(mysql_error());
}
// loop over the rows, outputting them
while ($row = mysql_fetch_assoc($rows)) fputcsv($output, $row);
Anyone with any other ideas?

See the manual
php://output is a write-only stream that allows you to write to the output buffer mechanism
in the same way as print and echo.
That really says it all.
So when you run this from a browser the standard output mechanism is send it to the browser as that is what echo or print would do. But in PHP CLI mode it sends the output to the terminal.
Answer is change this line from
$output = fopen('php://output', 'w');
to
$output = fopen($filename, 'w');
You then just have to decide if you are running through the browser or the CLI(cron job) and here is a suggestion
if ( php_sapi_name() !== 'cli' ) {
header("Content-type: text/csv; charset=UTF-8");
header("Content-Disposition: attachment; filename=" . $filename . ".csv");
readfile($filename);
}
You are going to have to check what your system reports using php_sapi_name() just to be sure you are testing for the right condition.

Related

How to correct filename value in Content-Disposition header?

This piece of code NEARLY solves my issue saving a query to .csv via php – however I can't understand why when it prompts me to save as export.csv, that file opens blank, while file.csv saves perfectly at the same time with the data I need. I'm sure it's something obvious going on with the headers. Can anyone help?
***EDIT below suggestions got me to this state and it no longer saves a file and prompts for a blank one but now the correct file shows with HTML crap in it. There is no other HTML in this script -- I've tried suggestions from many other posts. How can I solve?
$query = "SELECT * from Table";
$result = mysqli_query($connS, $query);
$headers = $result->fetch_fields();
foreach($headers as $header) {
$head[] = $header->name;
}
$fp = fopen('php://output', 'w');
header('Content-Disposition: attachment; filename="export.csv"');
header('Content-Description: File Transfer');
header('Content-Type: text/csv');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
fputcsv($fp, array_values($head));
while ($row = $result->fetch_array(MYSQLI_NUM)) {
fputcsv($fp, array_values($row));
}
$fp = fopen('file.csv', 'w');
readfile($fp);
fclose($fp);
end();
You're currently only saving the contents to file, not sending it to the user's browser. Perhaps try adding a call to readfile before your die statement.
So your last rows would look like this:
while ($row = $result->fetch_array(MYSQLI_NUM)) {
fputcsv($fp, array_values($row));
}
readfile($fp);
die;
}
Readfile reads a file and writes it to the output buffer. You can find more information on the readfile function here.
Note that the way you're currently doing it(saving to file before the user can download), if two users hit that page simultaneously, they would likely stomp on each others' toes(and create some odd intermix of the two created CSVs). You may want to try simply outputting the CSV contents directly to the user's browser, using the code in the accepted answer there. If you do that after your headers, it should result in the browser treating it like a file to be downloaded.

PHP & MYSQL blank result. Script suddenly stops. No errorlog

I want to wrtite a simple code that lets me download a file depending on the ID specified in the URL. For doing that, it connects to the database and tries to get the information of the file associated to the ID. Then, it sends the headers with the extracted info and the file.
But for reasons that I don't know, it outputs a blank page. There aren't any logfiles anywhere, just it suddenly stops.
Please, a bit of help would be really appreciated. Thanks you for spending your time
<?php
//We include the variables needed to do the connection to the db
include '../php/vars.php';
$id=$_GET['id'];
//We connect to the database
$con = mysql_connect("$dbsv","$dbuser","$dbpass");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("$dbname", $con);
// We do the query
if ($query === false) {echo mysql_error();}
$query = "SELECT name,filetype FROM links WHERE id=$id";
$result = mysql_query($query);
// Check result. This shows the actual query sent to MySQL, and the error. Useful for debugging.
if (!$result) {
$message = 'Invalid query: ' . mysql_error() . "\n";
$message .= 'Whole query: ' . $query;
die($message);
}
while ($row = mysql_fetch_assoc($result))
{
// Assign variables
$filename = $row['name'];
$type = $row['filetype'];
}
//We download the file
if (file_exists($filename)) {
header('Content-Description: File Transfer');
header( "Content-type: $type");
header('Content-Disposition: attachment; filename='.basename($filename));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filename));
fopen("$filename", "r");;
exit;
}
?>
I'm not native English. Expect gramatical, syntax and ortographical errors. If you detect them, please, notify me.
As I see you want to pass the file right?
fopen("$filename", "r");
replace this with
readfile($filename);
fopen just opens a file pointer and does absolutly nothing with the file itself, you have to use fread, write and fclose to do stuff with the file, there are more operations but basicly fopen just gives you a file pointer
There are a lot of logical errors, you need to fix:
if ($query === false) {echo mysql_error();}
$query is not set at this point. so it's never false. (You are saying basically if (null === false))
while ($row = mysql_fetch_assoc($result))
{
// Assign variables
$filename = $row['name'];
$type = $row['filetype'];
}
//We download the file
if (file_exists($filename)) {
Depending on your result count you are overriding $filename multiple times - and then only perform an operation on the LAST value.
Either move the logic into the while loop.
Or don't use a while-loop if you are expecting a single result.
Then:
fopen("$filename", "r");
You are opening a file - and then? doing nothing at all. Continue with fread() until EOF is reached and then use fclose($handle) bevor outputting the result.
(This is the reason for simply seeing nothing)
You would use readfile() instead. readfile() reads a file and writes it to the output buffer.
Here is manual link http://php.net/manual/en/function.readfile.php
if (file_exists($filename)) {
header('Content-Description: File Transfer');
header( "Content-type: $type");
header('Content-Disposition: attachment; filename='.basename($filename));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filename));
readfile($filename);
exit;
}

Saving Generated CSV to Server in Proper format as download

I've have been successful in exporting my database to csv as a downloadable file. However what I now need to do is instead of creating a straight .csv file that's downloaded I need it to just save to a folder called "csv" on the server. Here is my code for the current export. I need help in the saving it to server. I'm not saving the data correctly.
// output headers so that the file is downloaded rather than displayed
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=data.csv');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// output the column headings
fputcsv($output, array('tax_class_id','_product_websites'));
// fetch the data
mysql_connect('localhost:3036', 'x', 'x');
mysql_select_db('lato');
$rows = mysql_query('SELECT taxclass,productwebsite FROM product');
// loop over the rows, outputting them
while ($row = mysql_fetch_assoc($rows))
fputcsv($output, $row);
$filename = "data.csv"; // Trying to save file in server
file_put_contents("download/" . $filename, "$header\n$rows");
You need to change your last line to
$filename = "data.csv"; // Trying to save file in server
file_put_contents("download/" . $filename, $output);

php download file: header()

I need some eduction please.
At the end of each month, I want to download some data from my webserver to my local PC.
So, I've written a little script for that, which selects the data from the DB.
Next, I want to download it.
I've tried this:
$file=$month . '.txt';
$handle=fopen($file, "w");
header("Content-Type: application/text");
header("Content-Disposition: attachment, filename=" . $month . '.txt');
while ($row=mysql_fetch_array($res))
{
$writestring = $row['data_I_want'] . "\r\n";
fwrite($handle, $writestring);
}
fclose($handle);
If I run this, then the file is created, but my file doesn't contain the data that I want. Instead I get a dump from the HTML-file in my browser..
What am I doing wrong..
Thanks,
Xpoes
Below script will help you download the file created
//Below is where you create particular month's text file
$file=$month . '.txt';
$handle=fopen($file, "w");
while ($row=mysql_fetch_array($res)){
$writestring = $row['data_I_want'] . "\r\n";
fwrite($handle, $writestring);
}
fclose($handle);
//Now the file is ready with data from database
//Add below to download the text file created
$filename = $file; //name of the file
$filepath = $file; //location of the file. I have put $file since your file is create on the same folder where this script is
header("Cache-control: private");
header("Content-type: application/force-download");
header("Content-transfer-encoding: binary\n");
header("Content-disposition: attachment; filename=\"$filename\"");
header("Content-Length: ".filesize($filepath));
readfile($filepath);
exit;
Your current code does not output a file, it just sends headers.
in order for your script to work add the following code after your fclose statement.
$data = file_get_contents($file);
echo $data;

Save the results of a query to CSV and create a file on the server

First time I've had to do this, but I need to save the results of a query to CSV and create a file on the server, prior to it being passed via SFTP to a remote server. I can successfully create the CSV which is downloaded in the browser, per the code below, but cant seem to get it to save a file on the server. I think I may need file_put_contents? If anyone can suggest a method, or indeed a better approach to sending the outputs via sftp, its much apopreciated.
$result = mysql_query("SELECT * FROM `policy_details` WHERE `policyNumber` = '848938'");
if (!$result) die('Couldn\'t fetch records');
$num_fields = mysql_num_fields($result);
$headers = array();
for ($i = 0; $i < $num_fields; $i++)
{
$headers[] = mysql_field_name($result , $i);
}
$fp = fopen('php://output', 'w');
if ($fp && $result)
{
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="export.csv"');
header('Pragma: no-cache');
header('Expires: 0');
fputcsv($fp, $headers);
while ($row = mysql_fetch_row($result))
{
fputcsv($fp, array_values($row));
}
//die;
}
Immediate thought would be that you don't need to send headers when saving a file. If you are just saving a regular csv file to the local server (and doing the FTP thing separately), I also don't see the benefit of using the 'php://' scheme. I'd use something like
$fp = fopen('/path/to/new/file.csv', 'w+');
if ($fp && $result)
{
while ($row = mysql_fetch_row($result))
{
fputcsv($fp, array_values($row));
}
}
On the other hand, you could save the file directly over FTP, and avoid a 2 stage process.
What I would do is change your php://output file pointer to the file on the server that you want to save to. Move your headers below your while loop, that way you're writing each line from the db to the file. Once you exit your while loop, read the file that you just wrote as one big variable and print echo it with your headers.
$fp=fopen('/path/to/file/on/server/','w');
while ($row = mysql_fetch_row($result))
{
fputcsv($fp, array_values($row));
}
fclose($fp);
$csvFile = fopen('/path/to/file/on/server','r');
$csvData = fread($csvFile,filesize('/path/to/file/on/server');
fclose($csvFile);
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="export.csv"');
header('Pragma: no-cache');
header('Expires: 0');
echo $csvData;
Obviously this isn't the whole script, but these are the pieces I would change to accomplish what you want to do.

Categories