Thanks to the users community on this forum, I wrote a very simple web form that allows my user to view text files from within their Internet browser.
I have now two functions whereby the text files returned by the search are compressed into a ZIP. Here's my code
function getFilesFromSite() {
$result = null;
$ZIPresult = null;
if (empty($_POST['DBSite'])) { return null; }
$mydir = MYDIR;
$dir = opendir($mydir);
$DBSite = $_POST['DBSite'];
$getfilename = mysql_query("select filename from search_table where site='" . $DBSite . "'") or die(mysql_error());
while ($row = mysql_fetch_array($getfilename)) {
$filename = $row['filename'];
$result .= '<tr><td>' . $filename . '</td></tr>';
$ZIPresult .= basename($mydir) . '/' . $filename.' ';
}
if ($result) {
$result = "<table><tbody><tr><td>Search Results.</td></tr> $result</table>";
shell_exec("/bin/rm -f SearchResult.zip;/usr/bin/zip -9 SearchResult.zip ". $ZIPresult ." > /dev/null ");
//header for forced download
header("Pragma: public");
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
$fileName = 'SearchResult.zip';
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Transfer-Encoding: binary");
header('Content-type: application/zip');
header("Content-length: " . filesize($fileName));
header('Content-Disposition: attachment; filename="' . $fileName . '"');
ob_start(); // Starts output buffering.
readfile($fileName); // "Outputs" the file.
$content = ob_get_flush(); // Grabs the output and assigns it to a variable.
print base64_encode($content);
}
function getFilesFromError() {
//Just a copy paste from above with different input parameter...
}
The problem is that the ZIP file with the contents from whatever search was done first gets downloaded over and over again. For instance, the results from getFilesFromSite() will always get downloaded even though I did a search with getFilesFromError() afterwards.
I suspect my headers are incorrectly set but I am not sure where.
PS: The new ZipArchive() library/class is not available on our production environment so I chose to use the Unix utility ZIP instead.
Using Base64 was actually not working for reasons well stated here. Instead, I turned zlib compression off and reverted back to using binary as output format. Finally, I set Content-Type to application/octet-stream in my header. Everything is working fine now ; here's my code:
function getFiles() {
ini_set('zlib.output_compression', 'Off');
$result = null;
$ZIPresult = null;
$cleanup = null;
$output = null;
$fileName = null;
//remove old zip if any
$cleanup = shell_exec("/bin/rm -f SearchResult.zip");
error_log("SHELL OUTPUT=>" . $cleanup, 0);
//test
if (empty($_POST['DBRIDs'])) { return null; }
$mydir = MYDIR; // set from the CONSTANT
$dir = opendir($mydir);
$DBRIDs = $_POST['DBRIDs'];
$getfilename = mysql_query("select /*! SQL_CACHE */ filename from automation where rid in (" . $DBRIDs . ")") or die(mysql_error());
while ($row = mysql_fetch_array($getfilename)) {
$filename = $row['filename'];
$result .= '<tr><td>' . $filename . '</td></tr>';
$ZIPresult .= basename($mydir) . '/' . $filename.' ';
}
if ($result) {
$result = "<table><tbody><tr><td>Search Results.</td></tr> $result</table>";
$output = shell_exec("/usr/bin/zip SearchResult.zip ". $ZIPresult ." ");
error_log("SHELL OUTPUT=>" . $output, 0);
$fileName = 'SearchResult.zip';
error_log("ZIP FILENAME=>" . $fileName, 0);
if (file_exists($fileName)) {
//header for forced download
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($fileName));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($fileName));
ob_clean();
flush();
readfile($fileName);
exit;
}
}
return $result;
}
Thanks to all for taking the time!!
Related
I am currently having a problem with my PHP code as it corrupts the data/xlsx file when exporting it from HTML.
i am viewing PHP Mailer scripts which has multiple pages connected to it.
This is my PHP XLS Function.
this->_request->download ? true : false;
$htmlPath = realpath(dirname(__FILE__) . "/../../public/reports/html/") . "/" . $fileName;
$fileSource = file_get_contents($htmlPath);
preg_match('!<title>([^<]+)!', $fileSource, $title);
$title = trim($title[1]);
if (stristr($fileSource, '<graph>')) {
$fileSource = preg_replace('!<graph>[^<]+</graph>!is', '', $fileSource);
file_put_contents($htmlPath, $fileSource);
}
file_put_contents($htmlPath,preg_replace('!<title>[^<]+</title>!is','',$fileSource));
$reader = new PHPExcel_Reader_HTML;
$content = $reader->load($htmlPath);
// Pass to writer and output as needed
$objWriter = PHPExcel_IOFactory::createWriter($content, 'Excel2007');
$download = 1;
// Redirect output to a client’s web browser (Excel5)
//header('Content-Type: application/vnd.ms-excel');
$fileName = str_replace(' ', '-', ($title . "-" . date('Y-m-d')));
if ($download) {
// Redirect output to a client’s web browser (Excel2007)
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Cache-Control: max-age=0');
// If you're serving to IE 9, then the following may be needed
// header('Cache-Control: max-age=1');
// If you're serving to IE over SSL, then the following may be needed
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
header('Pragma: public'); // HTTP/1.0
header('Content-Disposition: attachment;
filename=' . $fileName . ".xlsx")
this is my caller function
if ($reportRow->reportString) {
$reportRow->reportString = stripslashes($reportRow->reportString);
if (!stristr($reportRow->reportString, '</body>'))
$reportRow->reportString = $reportRow->reportString . "</table></body></html>";
$fileName = time() . rand(111, 222);
$htmlPath = realpath(dirname(__FILE__) . "/../../public/reports/html/") . "/" . $fileName;
if ($headerPath) {
$reportRow->html_string = preg_replace('!(\s*</htmlpageheader>)!', '$1<img width="100%" style="clear:both" id="headerPath" src="' . $headerPath . '" />', $reportRow->html_string);
}
$corp_name = preg_replace('!\s+!',' ',$userSessionData->corp_name);
$reportRow->reportString = preg_replace_callback(
'!<title>([^<]+)!is',
function($matches) use ($corp_name){
return '<title>' . $corp_name . '_' . preg_replace('!\s+!',' ',$matches[1]);
},
$reportRow->reportString
);
file_put_contents($htmlPath, $reportRow->reportString);
$kilobites = filesize($htmlPath);
$kilobites = $kilobites / 1024;
$kilobites = 0;
if ($ifXLS) {
echo json_encode(array(
'reportPath' => '/helper/file-To-xls/fileName/' . $fileName,
'error' => false
));
would anyone have any ideas on how to fix this issue?
you can use CSV functions or PHPExcel to do it straight forward
or you can try like below
<?php
$file="1.xls";
$html="<table><tr><td>Col1</td><td>Col2</td></tr></table>";
header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=$file");
echo $html;
?>
The header for .xlsx files is Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet if you prefer to export it as .xlsx
The following file (which I don't understand it at all) serves my requested file and makes it ready to be downloaded. But, the links that are created and served by this file miss really important items when downloading by IDM.
File size: (unknown), Time left (unknown) , Resume capability (unknown).
Very unprofessional and bad in all aspects. What should I do as a novice?
if (isset($status) && ($status == 'd')) { //if Every Thing Is Fine The Download Start
$filename = $url;
$extension = fileexten($filename);
$fakename = fakefilename($downcode);
$mime = contenttype($extension);
// set_time_limit(0);
if ($notadownload == FALSE) {
header('Pragma: public');
header('Expires: 0');
header("Content-Type:" . $mime);
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Disposition: attachment;filename=' . $fakename . '.' . $extension);
header("Content-Transfer-Encoding: binary");
ob_clean();
flush();
#readfile($filename);
} else {
$mime = getContentType($filename);
header("Content-Type:" . $mime);
if (strpos($mime, 'text') == FALSE) {
$extension = fileexten($filename);
header('Content-Disposition: inline;filename=' . $fakename . '.' . $extension);
}
echo #file_get_contents($filename);
}
}
Actually i want to change opencart download routh to new website, already download folder is:
/system/download
config.php
define('DIR_DOWNLOAD', '/system/download/');
and here is code from controller/account/download.php
if ($download_info) {
$file = DIR_DOWNLOAD . $download_info['filename'];
$mask = basename($download_info['mask']);
if (!headers_sent()) {
if (file_exists($file)) {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . ($mask ? $mask : basename($file)) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
if (ob_get_level()) {
ob_end_clean();
}
readfile($file, 'rb');
exit();
} else {
exit('Error: Could not find file ' . $file . '!');
}
} else {
exit('Error: Headers already sent out!');
}
} else {
$this->response->redirect($this->url->link('account/download', '', 'SSL'));
}
i want to buy a new server just for downloading, and now i want change opencart download route to new server. how can i do this?
Already download system is like this:
https://example.com/index.php?route=account/download/download&download_id=16
and it will get file from this directory:
/system/download/example.zip
but i want to get file from new server:
https://newserver.com/download/example.zip
Is it possible? I changed DIR_DOWNLOAD but no success. Any idea?
Yes you can, go with this easily:
$newserv = "http://newserver.com/";
$file = $newserv . $download_info['filename'];
$mask = basename($download_info['mask']);
I want to paste one script in all my client machine which call php file which is on my server.
Let say my server path is www.google.com/support/lokesh.php
So that I want to put one file to all my client machine at location where it call php file(for example if it call from /home/lalu/myscript.sh) then my php code will put one file(additional.sh) to /home/lalu/additional.sh
below is my code to download file
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename('google.com/support/lokesh.txt'));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('/home/lokesh/lalu.txt'));
readfile('/home/lokesh/lalu.txt');
//for sending mail fif only one user is available
exit;
I want to paste one file location at client machine from where it call server file.
One attempt, with a progress bar.
#!/usr/bin/php
<?php
if (#$argv[1] != null){
echo "Retrieving http header...";
$header = get_headers("$argv[1]");
$pp = "0";
echo json_encode($header, JSON_PRETTY_PRINT);
$key = key(preg_grep('/\bLength\b/i', $header));
$type = key(preg_grep('/\bType\b/i', $header));
$http = substr($header[0], 9, 3);
$tbytes = #explode(" ",$header[$key])[1];
$type = #explode("/",explode(" ",$header[$type])[1])[1];
echo " Target size: ".floor((($tbytes / 1000)/1000))." Mo || ".floor(($tbytes/1000))." Kb";
$t = explode("/",$argv[1]);
$remote = fopen($argv[1], 'r');
$nm = $t[count($t)-1].".$type";
$local = fopen($nm, 'w');
$read_bytes = 0;
echo PHP_EOL;
while(!feof($remote)) {
$buffer = fread($remote, intval($tbytes));
fwrite($local, $buffer);
$read_bytes += 2048;
$progress = min(100, 100 * $read_bytes / $tbytes);
$progress = substr($progress,0 , 6) *4;
$shell = 10; /* Progress bar width */
$rt = $shell * $progress / 100;
echo " \033[35;2m\e[0m Downloading: [".round($progress,3)."%] ".floor((($read_bytes/1000)*4))."Kb ";
if ($pp === $shell){$pp=0;};
if ($rt === $shell){$rt=0;};
echo str_repeat("█",$rt).str_repeat("=",($pp++)).">#\r";
usleep(1000);
}
echo " \033[35;2m\e[0mDone [100%] ".floor((($tbytes / 1000)/1000))." Mo || ".floor(($tbytes/1000))." Kb \r";
echo PHP_EOL;
fclose($remote);
fclose($local);
}
The file is build directly into the current folder, not in the temp directory.
This mean the file can be read while downloading.
If the file type is made to handle that, like most media format do.
To use, pass an url as first argument in the command line.
./pget https://site.download.mp4
You know you want to tweek it ;)
In my opinion, the easiest way is:
$fileContent = file_get_contents('/home/lokesh/lalu.txt');
If I correctly understood.
Try this code. In your download file :
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/".$extension); // you can put here MIME type of your file
header("Content-Disposition: attachment; filename=\"" . basename($filePath) . "\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filePath));
set_time_limit(0);
readfile("$filePath");
When using computer files are downloaded normally.
Problem start on android browsers.
When we download a file from android default browser, the file is downloaded but it is of 0.00 bytes, so not technically present there(corrupt file).
When we download file from any third party application like or opera it gives error that "file could not be downloaded." not the header error. And files could be downloaded via UC Browser and Chrome and Firefox. But still gives the error in default browser.
Here is the code I am using:
<?php
require 'php/db.php';
if(isset($_POST['file_id'])&&!empty($_POST['file_id'])){
download_file($_POST['file_id']);
}
function download_file($id){
global $con;
$id = mysqli_real_escape_string($con,htmlentities($id));
$file="SELECT file_name,file_title,file_size,down FROM files WHERE file_id= $id";
$result = mysqli_query($con,$file);
$row = mysqli_fetch_assoc($result);
$name = $row['file_name'];
$title = $row['file_title'];
$size = $row['file_size'];
$ext = strtoupper(ext($name)); // Function defined bellow
$down = $row['down'];
$newname = $title.'.'.$ext;
$olddir = "files/".$name;
$down++;
if(is_file($olddir)) {
$update_down = "UPDATE files SET down = $down WHERE file_id = '$id'";
$update_down_result = mysqli_query($con,$update_down);
header('Pragma: public'); // required
header('Expires: 0'); // no cache
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($olddir)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$newname.'"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.$size); // provide file size
header('Connection: close');
readfile($olddir);
exit();
}else header("Location: index.php?msg=Sorry!+File+could+not+be+downloaded");
}
function ext($name){
$rut = strrev($name);
$erut = explode('.', $rut);
return strrev($erut[0]);
}
We give file id to this function and it downloads the file on PC.
Can anyone tell me how to remove the error? So that users can download files from their android phones too.
Probably $size == 0;
$size = $row['file_size'];
...
$olddir = "files/".$name;
change to
$olddir = "files/".$name;
$size = filesize($olddir);
And change
else header("Location: index.php?msg=Sorry!+File+could+not+be+downloaded");
to
else header("Location: index.php?msg=Sorry!+File+could+not+be+found+on+server: " . $olddir);
I got the solution.
Mainly I changed two things:
Used GET method instead of Post Method.
Used Flush and ob_clean functions to clear the buffer.
New code for downfile.php is like this:
<?php
require '../php/db.php';
ob_start();
if(isset($_GET['file_id'])&&!empty($_GET['file_id'])){
download_file($_GET['file_id']);
}else die("There was an error in downloading file. Please try again later.");
function download_file($id){
global $con;
$id = mysqli_real_escape_string($con,htmlentities($id));
$file="SELECT file_name,file_title,file_size,down FROM files WHERE file_id= $id";
$result = mysqli_query($con,$file);
$row = mysqli_fetch_assoc($result);
$name = $row['file_name'];
$title = $row['file_title'];
$ext = ext($name);
$down = $row['down'];
$newname = $title.'.'.$ext;
$size = $row['file_size'];
$down++;
if(is_file($name)) {
$update_down = "UPDATE files SET down = $down WHERE file_id = '$id'";
$update_down_result = mysqli_query($con,$update_down);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$newname.'"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: '.$size);
ob_clean();
flush();
readfile($name);
exit;
}else header("Location: index.php?msg=Sorry!+File+could+not+found!");
}
function ext($name){
$rut = strrev($name);
$erut = explode('.', $rut);
return strrev($erut[0]);
}
?>
Through this code I am able to download files in android browsers too.
Hope this may help. :)