PHP text file auto download giving error headers already sent - php

I am uploading text file and then converting it after conversion I am forcing it to auto download that converted text file, but it's not getting downloaded, giving error Warning: Cannot modify header information - headers already sent
Force download text file PHP code
if (file_exists($fileCreate)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($fileCreate));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($fileCreate));
ob_clean();
flush();
readfile($fileCreate);
exit;
}
}
Full PHP code
<?php
error_reporting(E_ALL & ~E_NOTICE);
if(!empty($_FILES['uploaded_file']))
{
$path = "upload/";
$path = $path . basename( $_FILES['uploaded_file']['name']);
if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $path)) {
echo "The file ". basename( $_FILES['uploaded_file']['name']).
" has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
$count = 0;
$fileCreate = 'order-'.date('m-d-Y').".txt";
$myfile = fopen("$fileCreate","w") or die("Unable to open file!");
fwrite($myfile, "1"."\n");
if($file = fopen("$path", "r")){
while(!feof($file)) {
$line = fgets($file);
$keywords = preg_split("/[\s,]+/", $line);
$x = $keywords[2];
$y = 5;
$y .= $x;
$y .= "001";
$date = $keywords[1];
$date1 = str_replace('"','',$date);
$newDate = date("Y/m/d", strtotime($date1));
$y .= str_replace("/", "", $newDate);
$y .= " ";
$fso = $keywords[3];
$fso = str_replace('"','',$fso);
$y .= $keywords[3];
if($fso != "FPO" || $fso != "APO"){
$y .= $keywords[4];
}
$y = str_replace('"','',$y);
$storeValue[$count]=$y;
fwrite($myfile, $y."\n");
$count++;
}
$str = strval($count);
$strlen = strlen($str);
if($strlen == 1){
$footer = 900000;
}
else if($strlen == 2){
$footer = 90000;
}
else if($strlen == 3){
$footer = 9000;
}
else if($strlen == 4){
$footer = 900;
}
else if($strlen == 5){
$footer = 90;
}
else{
$footer = 9;
}
$footer .= $count;
$footerDate = date("Y/m/d");
$footer .= str_replace("/", "", $footerDate);
fwrite($myfile, $footer."\n");
fclose($file);
}
if (file_exists($fileCreate)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($fileCreate));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($fileCreate));
ob_clean();
flush();
readfile($fileCreate);
exit;
}
}
?>
UPDATE: It's fixed by adding output_buffering = ON in php.ini file

Two things.
1) You need to start session immediately after the <?php
2) You session redirect does not work if something output before the session redirect (header location).
What you can do is,
You can use javascript for redirecting.
echo '<script>window.location.replace("http://stackoverflow.com");</script>';
Anyway if you are using sessions, start session on the top of page (session_start()).
<?php
session_start();
error_reporting(E_ALL & ~E_NOTICE);
if(!empty($_FILES['uploaded_file']))

Update
It's fixed by adding output_buffering = ON in php.ini file

Related

Large files failing to download using readfile()

I have the following code to force download an IPA file (after codesigning it with a script). It works fine with smaller files but with larger files, my web server starts returning a 500 Internal Server Error. Would someone be able to help me tweak my existing code to overcome this issue?
$time = md5(time());
// Runs code signing script here
// And then attempts to initiate download
$path = "done/$time/";
$latest_ctime = 0;
$latest_filename = '';
$d = dir($path);
while (false !== ($entry = $d->read())) {
$filepath = "{$path}/{$entry}";
if (is_file($filepath) && filectime($filepath) > $latest_ctime) {
$latest_ctime = filectime($filepath);
$latest_filename = $entry;
}
}
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$time.ipa");
header("Content-Type: application/ipa");
header("Content-Transfer-Encoding: binary");
// Read the file from disk
readfile("done/$time/".$latest_filename);
// header('location: dashboard.php');
} else {
// Throwback
die("Failed. Contact support. // <p>$sign</p>");
}
Here is an example:
$filepath = "done/{$time}/{$latest_filename}";
$size = filesize($filepath);
$mimetype = 'application/ipa';
// Turn off buffering
if (ob_get_level()) {
ob_end_clean();
}
$handle = fopen($filepath, 'rb');
if ($handle !== false && $size > 0) {
#flock($handle, LOCK_SH);
$filename = rawurldecode($filepath);
$old_max_execution_time = ini_get('max_execution_time');
$old_cache_limiter = session_cache_limiter();
ini_set('max_execution_time', 0);
session_cache_limiter(false);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header('Content-Type: ' . $mimetype);
header('Content-Transfer-Encoding: binary');
header('Content-disposition: attachment; filename="'. $filename .'"');
// or your variant
// header("Content-Disposition: attachment; filename=" . md5(time()));
header("Content-Length: $size");
$start = 0;
$end = $size - 1;
$chunk = 8 * 1024;
$requested = (float)$end - (float)$start + 1;
while (! $error) {
if ($chunk >= $requested) {
$chunk = (integer)$requested;
}
set_time_limit(0);
while (! feof($handle) && (connection_status() === 0)) {
if (! $buffer = #fread($handle, $chunk)) {
$error = true;
break 2;
}
print($buffer);
flush();
}
#flock($handle, LOCK_UN);
#fclose($handle);
ini_set('max_execution_time', $old_max_execution_time);
session_cache_limiter($old_cache_limiter);
break;
}
if ($error) {
// 500 - Internal server error
exit;
}
} else {
// Can't open file
exit;
}
Maybe problem in script time execution.
Try to set ini_set('max_execution_time', 0);
Also try to read and send file by chunks.

PHP readfile() echoes file content to the screen, but doesn't download

the code I am using:
function DownLoading($Peter)
{
// if(ini_get('zlib.output_compression'))
// ini_set('zlib.output_compression', 'Off')
$File = "";
$Filename = "";
If ($Peter == "Farm") {
$File = "TestFile.txt";
$FileName = $File; //"TestFile.txt";
$len = filesize($File); // Calculate File Size
if (file_exists("TestFile.txt")) {
header('Content-Description: File Transfer');
header('Content-Type: text/plain');
header('Content-Disposition: attachment; filename="TestFile.txt"');
header('Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $len);
ob_clean();
$wasdownloaded = readfile("TestFile.txt");
if ($wasdownloaded === false)
echo "error";
else {
echo "no error";
Flush();
exit;
}
}
}
}
The strange thing is that if I run this code on wamp server then it works fine (no echoeing, but downloading)
The following is echoed to the sdcreen: This is a test file!!! Nowno error
whereby "This is a test file!!! NOW" is the files's content
Can somebody help me?
I did something very stupid that was causing the same thing. Basically, as already said, you must ensure nothing has been sent already.
I had put a space before the <?php opening declaration - and that was the problem!

Force downloading files with foreign characters

How can I force the download of files whose file name contains more characters than English, for example Swedish, Norwegian like ö ä å . It's working perfect if the file is without ö ä å but not if file name holds Swedish characters.
The following is the code that I use to open files.
$file_id = $_GET['f'];
$sql = " SELECT * ".
" FROM attachment ".
" WHERE attachment_id = ".$file_id." ".
$res = mysql_query($sql);
$row = mysql_fetch_array($res);
$filename = $row['filename'];
$USER_ID = $row['user_id'];
$DIRECTORY_ID = $row['directory_id'];
$target_path = "upload/".$USER_ID."/".$DIRECTORY_ID."/";
// And the function is :
function Download($path, $speed = null)
{
if (is_file($path) === true)
{
$file = #fopen($path, 'rb');
$speed = (isset($speed) === true) ? round($speed * 1024) : 524288;
if (is_resource($file) === true)
{
set_time_limit(0);
ignore_user_abort(false);
while (ob_get_level() > 0)
{
ob_end_clean();
}
header('Expires: 0');
header('Pragma: public');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Type: application/octet-stream');
header('Content-Length: ' . sprintf('%u', filesize($path)));
header('Content-Disposition: attachment; filename="' . basename($path) . '"');
header('Content-Transfer-Encoding: binary');
while (feof($file) !== true)
{
echo fread($file, $speed);
while (ob_get_level() > 0)
{
ob_end_flush();
}
flush();
sleep(1);
}
fclose($file);
}
exit();
}
return false;
}
Download($target_path.$filename);
I have used:
$filename = urlencode($filename);
$filename = htmlentities($filename, ENT_QUOTES, "UTF-8");
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
and
$path = iconv('UTF-8', 'ASCII//TRANSLIT', $path)
But nothing is working.
I want to thank you in advance and Any help you can give will be greatly appreciated.
Jonas.
use this:
<?php
header('Content-Type: text/html; charset=utf-8');
?>
and be sure that you save your PHP Source file as utf-8.

How to echo date in php

this code is doing Zip & Download perfect but i want to change a time to date how can i do this
when i save a folder its save with time i want to save with date how can i do this
this is time script how can i change in to date when i change Y-m-d but this is not working its showing this error Parse error: syntax error, unexpected T_STRING in downloadlist.php on line 26
please help me to fix this issue
thanks
$filename = Y-m-d " Backup.zip"; (not working)
$filename = time() ." Backup.zip"; ( working code)
downloadlist.php
<?php
// function download($file) downloads file provided in $file
function download($file) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
$files = $_POST['file'];
if(empty($files))
{
echo("You haven't selected any file to download.");
}
else
{
$zip = new ZipArchive();
$filename = time() ." Backup.zip"; //adds timestamp to zip archive so every file has unique filename
if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { // creates new zip archive
exit("Cannot open <$filename>\n");
}
$N = count($files);
for($i=0; $i < $N; $i++)
{
$zip->addFile($files[$i], $files[$i]); //add files to archive
}
$numFiles = $zip->numFiles;
$zip->close();
$time = 8; //how long in seconds do we wait for files to be archived.
$found = false;
for($i=0; $i<$time; $i++){
if($numFiles == $N){ // check if number of files in zip archive equals number of checked files
download($filename);
$found = true;
break;
}
sleep(1); // if not found wait one second before continue looping
}
if($found) { }
else echo "Sorry, this is taking too long";
}
?>
list.php
<?php
function listDir($dirName)
{
$forbidden_files=array('.htaccess','.htpasswd');
$allow_ext=array('.pdf','.doc','.docx','.xls','.xlsx','.txt');
?><form name="filelist" action="downloadList.php" method="POST"><?php echo "\n";
if ($handle = opendir($dirName)) {
while (false !== ($file = readdir($handle)) ) {
$allowed=(strpos($file,'.')!==false && in_array(substr($file,strpos($file,'.')) ,$allow_ext ));
if ($file != "." && $file != ".." && $allowed ) { ?> <input type=checkbox name="file[]" value="<?php echo "$file";?>"><?php echo "$file"; ?><br><?php echo "\n";
}
}
closedir($handle);
}
?><br><input type="submit" name="formSubmit" value="Zip and download" /></form><?php
}
listDir('.'); ?>
$filename = Y-m-d " Backup.zip"; (not working)
because you are not using date() here. Also, you are not concatenating strings using ..
$filename = date('Y-m-d')."Backup.zip";
The above code will work for you.

There's some html content in a file which is downloaded using PHP scripts on firefox

I use the following to download a file with PHP:
ob_start();
$browser = id_browser();
header('Content-Type: '.(($browser=='IE' || $browser=='OPERA')?
'application/octetstream':'application/octet-stream'));
header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize(realpath($fullpath)));
//header("Content-Encoding: none");
if($browser == 'IE')
{
header('Content-Disposition: attachment; filename="'.$file.'"');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
} else
{
header('Content-Disposition: attachment; filename="'.$file.'"');
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
}
//#set_time_limit( 0 );
ReadFileChunked(utf8_decode($fullpath));
ob_end_flush();
The source code of ReadFileChunked is:
function ReadFileChunked($filename,$retbytes=true)
{
$chunksize = 1*(1024*1024);
$remainFileSize = filesize($filename);
if($remainFileSize < $chunksize)
$chunksize = $remainFileSize;
$buffer = '';
$cnt =0;
// $handle = fopen($filename, 'rb');
//echo $filename."<br>";
$handle = fopen($filename, 'rb');
if ($handle === false) {
//echo 1;
return false;
}
//echo 2;
while (!feof($handle))
{
//echo "current remain file size $remainFileSize<br>";
//echo "current chunksize $chunksize<br>";
$buffer = fread($handle, $chunksize);
echo $buffer;
sleep(1);
ob_flush();
flush();
if ($retbytes) {
$cnt += strlen($buffer);
}
$remainFileSize -= $chunksize;
if($remainFileSize == 0)
break;
if($remainFileSize < $chunksize)
{
$chunksize = $remainFileSize;
}
}
$status = fclose($handle);
if ($retbytes && $status) {
return $cnt; // return num. bytes delivered like readfile() does.
}
return $status;
}
The question is :
The file downloaded will contiain some html tags which are the content of the html code generated by the php.
The error will happened when downloading the txt file with the file size smaller than 4096 bytes.
Please help me to slove this problem , thank you very much!
Chu
Have you tried using fpassthru rather than your custom function.
There's no need to use the $chunksize stuff in there. fread() automatically stops reading once it reaches the end of the file, even if the $chunksize would normally tell it to read more. As well, you should probably put your ob_flush() and flush() calls BEFORE the sleep(1). That way the data you've just placed in the output buffer can get sent off to the webserver without having to wait the one second needlessly.
In fact, you could replace the whole function with the following:
function ReadFileChunk($filename, $retbytes = true) {
$fh = fopen($filename, 'rb');
if (!$fh) {
return(false);
}
while($buf = fread($fh, 4096)) {
echo $buf;
ob_flush();
flush();
sleep(1);
}
$status = fclose($fh);
return( $retbytes ? filesize($filename) : $status);
}
But why bother rolling your own when readfile() already exists? It will handle the whole business of opening the file, and sending it in normal-sized pieces that won't exceed memory_limit.

Categories