downloading a csv file - php

im having a problem when downloading a csv file using php, ideally i want to visit a page and it just prom,pts me to save the file-
i have tried this here-
$filename = 'dump.csv';
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
and it has been returning a empty file, even though when i do-
echo filesize($filename);
it returns 19000 ?

You have to read the content of the file in and then output it.
Otherwise you are just sending the headers telling the browser to expect the file.

You would need to echo out the contents of the file. For example, after your header functions you would have something like:
$fh = fopen($filename, "r");
while($line = fgets($fh)){
echo $line;
}
fclose($fh);

Related

PHP Output MS SQL to a downloadable CSV or Excel file

I'm trying to output data returned by an MS SQL query to an Excel or CSV file with PHP.
I've used the script in this answer and can output the file OK. Without the header lines (at the bottom of my code) it saves in my server's folder structure rather than outputs as a download to the browser.
If I add the header lines, it ouputs to a CSV file but writes the page's HTML to the file rather than the extract from the database! Am I missing a setting somewhere? I tried running the code on a page with no HTML in it (PHP and SQL code only), but it still happens.
// Give the file a suitable name:
$FileName= $PartNumber.".csv";
$fp = fopen($FileName, 'w');
// Connect to MS SQL server; the actual database is chosen in the form
// ConnSQL defined in inc/dbconn/config.php
ConnSQL($idDatabase);
// the query is a biggie; here it is:
require 'inc_sql.php';
// run it through the SQL server
$rstBOM = sqlsrv_query($GLOBALS['ConnSQL'], $sqlBOM);
while ($export= sqlsrv_fetch_array($rstBOM, SQLSRV_FETCH_ASSOC)) {
if (!isset($headings))
{
$headings = array_keys($export);
fputcsv($fp, $headings, ',', '"');
}
fputcsv($fp, $export, ',', '"');
}
// force download csv - exports HTML to CSV!
header("Content-type: application/force-download");
header('Content-Disposition: inline; filename="'.$FileName.'"');
header("Content-Transfer-Encoding: Binary");
header("Content-length: ". filesize($FileName));
header('Content-Type: application/excel');
header('Content-Disposition: attachment; filename="'.$FileName.'"');
fclose($fp);
Any ideas where I'm going wrong please?
You need to output your csv file to the browser simply by putting
readfile($FileName);
At the end of your code after the fclose($fp); function.
Otherwise, browser receives the headers for files, but no content in sent from your PHP code.
You could also generate your csv file on the fly and just echo $csvFileContents; instead. This would prevent server from creating and writing data to file, which could lead to security breaches.
Good luck!

PHP Download - File emty [duplicate]

The end goal is for the user to download a .csv file. Right now I'm just testing trying to download a simple text file: test.txt. The only thing in this file is the word "test".
Here is the HTML code for files_to_download.php
Test file: <a href='test.php?file=test.txt'>Test.txt</a>
Code for test.php:
if(!(empty($_GET["file"])))
{
$file_name = $_GET["file"];
$path = "path/to/file";
$fullPath = $path . $file_name;
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: inline; attachment; filename=\"$file_name\"");
header("Content-Type: text/plain");
header("Content-Transfer-Encoding: binary");
readfile($fullPath);
}
I've tried variations of the headers above, adding more and removing others. The above seem to be the most common recommended on this site.
I've also tried changing
header("Content-Type: text/plain");
to
header("Content-Type: text/csv");
and get same results: empty .txt or .csv file.
The files are not empty when I open them directly (file browser) from the server. I've checked the permissions of the files and they're both 644, so the entire world can at least read the files. The directory is 777.
Is there a configuration on the Apache server I need to specify that may not be or am I missing something above.
Thanks for looking!
In most cases the path is wrong
Read the text file, then echo the text out after your header() calls.
Here's how I have my csv download set up:
//downloads an export of the user DB
$csv = User::exportUsers();
header('Content-disposition: attachment; filename=userdb.csv');
header('Content-type: text/csv');
echo $csv;
Where exportUsers() creates the csv data. You can easily just replace $csv with the contents of your text file, then echo it out.
And as far as your text file, you can use file_get_contents() to get the contents of your file into a string. Then echo that string.
Try setting the content length of the file:
header('Content-Length: ' . filesize($file));
Also, please have this in mind: file inclusion
In my case, the path was correct. And the download-forcing was working on windows, but not mac.
I figured out after few tests that the header Content-Length was failing. I was using the function filesize on a full url, like :
$url_my_file = "http://my-website.com/folders/file.ext";
header('Content-Length: '.(filesize($url_my_file)));
I replace it by
$url_my_file = "http://my-website.com/folders/file.ext";
$headers = get_headers($url_my_file, 1);
header('Content-Length: '.($headers['Content-Length']));
And ... It's working now :)

How to read huge file and output it with php

I want to handle big files(1-2Gb) downloads with php script and found two ways to do that:
with file_get_contents()
with readfile()
and use this implementation:
header('Content-type: ' . $string);
header('Content-disposition: attachment; filename=' . $info['filename']);
$file = file_get_contents($filename);
echo $file;
or
readfile($filename);
But it takes too long to output the file. I suppose that the whole file has to be readed, before the output starts.
It is more quickly when point the exact location of the file. Then it starts the output almost immediately.
I am looking for solution that streams the file or something. Any ideas?
You should consider using mod_xsendfile
$handle = fopen($this->_path, 'rb');
while(!feof($handle))
{
echo fread($handle, 4096);
ob_flush();
flush();
}
fclose($handle);
from PHP Readfile() not working for me and I don't know why

Force download file with PHP giving empty file

The end goal is for the user to download a .csv file. Right now I'm just testing trying to download a simple text file: test.txt. The only thing in this file is the word "test".
Here is the HTML code for files_to_download.php
Test file: <a href='test.php?file=test.txt'>Test.txt</a>
Code for test.php:
if(!(empty($_GET["file"])))
{
$file_name = $_GET["file"];
$path = "path/to/file";
$fullPath = $path . $file_name;
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: inline; attachment; filename=\"$file_name\"");
header("Content-Type: text/plain");
header("Content-Transfer-Encoding: binary");
readfile($fullPath);
}
I've tried variations of the headers above, adding more and removing others. The above seem to be the most common recommended on this site.
I've also tried changing
header("Content-Type: text/plain");
to
header("Content-Type: text/csv");
and get same results: empty .txt or .csv file.
The files are not empty when I open them directly (file browser) from the server. I've checked the permissions of the files and they're both 644, so the entire world can at least read the files. The directory is 777.
Is there a configuration on the Apache server I need to specify that may not be or am I missing something above.
Thanks for looking!
In most cases the path is wrong
Read the text file, then echo the text out after your header() calls.
Here's how I have my csv download set up:
//downloads an export of the user DB
$csv = User::exportUsers();
header('Content-disposition: attachment; filename=userdb.csv');
header('Content-type: text/csv');
echo $csv;
Where exportUsers() creates the csv data. You can easily just replace $csv with the contents of your text file, then echo it out.
And as far as your text file, you can use file_get_contents() to get the contents of your file into a string. Then echo that string.
Try setting the content length of the file:
header('Content-Length: ' . filesize($file));
Also, please have this in mind: file inclusion
In my case, the path was correct. And the download-forcing was working on windows, but not mac.
I figured out after few tests that the header Content-Length was failing. I was using the function filesize on a full url, like :
$url_my_file = "http://my-website.com/folders/file.ext";
header('Content-Length: '.(filesize($url_my_file)));
I replace it by
$url_my_file = "http://my-website.com/folders/file.ext";
$headers = get_headers($url_my_file, 1);
header('Content-Length: '.($headers['Content-Length']));
And ... It's working now :)

PHP forcing file download. Not showing what amount of space has been downloaded

I have a issue, I have a PHP script that compresses images in a Zip file and then forcing the zip file to download. Now my issue is it's not showing in IE how much space has been downloaded sofar. Eg 2MB's out of 20MB's..... 15secs remaining. Firefox works perfect.
My code
header("Content-Disposition: attachment; filename=" . urlencode($zipfile));
header("Content-Type: application/x-zip-compressed");
header("Content-Description: File Transfer");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($filename));
$fd = fopen($filename,'r');
$content = fread($fd, filesize($filename));
print $content;
The main issue, as noted in the comment, is that you are storing the whole file into memory prior to sending which may cause a very long wait depending on file size. What you would prefer to do is output the buffer as segments are read into memory, in 1024 byte blocks, for example.
You could try something more along the lines of:
if ($file = fopen($filename, 'rb')) {
while(!feof($file)) {
print(fread($file, 1024*8));
flush();
}
fclose($file);
}
Which will not attempt to read the entire file prior to output, but rather output blocks of the file as they are read into the output buffer.

Categories