How to download file via command line in php? - php

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");

Related

Forcing PHP to download file via browser

I'm currently trying to make a file download in the user's browser but have so far been unable to make it happen.
I've looked at other answers on stackoverflow.com and so far haven't found anything that has solved my problem.
My process is as follows:
I create the filename and filepath, then set headers:
$date = new DateTime();
$currentDateTime = $date->format("Y-m-d H:i:s");
$filename = "{$name}_{$currentDateTime}.csv";
$filepath = $rootfull . "/{$filename}";
// Set headers
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="' . $filepath . '"');
header('Content-Length: ' . filesize($filepath));
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: no-cache');
I then create the file and start writing to it:
// Write header
fputcsv($output, $header);
fputcsv($output, array()); // Empty line
// Write column names
$column_headers = array_keys(array_flip($columns));
foreach ($data as $row)
{
fputcsv($output, $row);
}
echo readfile($filepath);
die();
The file gets generated and written to the specified location (in this case /var/www/<project>/<filename>.csv without any indication to the user that anything has happened. No download dialog, nothing.
If anyone can spot a problem with my code or my process, please point it out and preferably suggest a better/alternative way of doing it, any help at all is welcome at this point.
If no benefit (poor mans cache) to writing to disk then maybe something like this writing to buffer:
<?php
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="dump_' . date('Ymd') . '.csv"');
header("Pragma: no-cache");
header("Expires: 0");
$this->outputCSV($results);
exit(); //->
public function outputCSV($data, $useKeysForHeaderRow = true)
{
if ($useKeysForHeaderRow) {
array_unshift($data, array_keys(reset($data)));
}
$outputBuffer = fopen("php://output", 'w');
foreach($data as $v) {
fputcsv($outputBuffer, $v);
}
fclose($outputBuffer);
}
?>

Not able to download files with php in android browsers

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. :)

Serve file to user over http via php

If I goto http://site.com/uploads/file.pdf I can retrieve a file.
However, if I have a script such as:
<?php
ini_set('display_errors',1);
error_reporting(E_ALL|E_STRICT);
//require global definitions
require_once("includes/globals.php");
//validate the user before continuing
isValidUser();
$subTitle = "Attachment";
$attachmentPath = "/var/www/html/DEVELOPMENT/serviceNow/selfService/uploads/";
if(isset($_GET['id']) and !empty($_GET['id'])){
//first lookup attachment meta information
$a = new Attachment();
$attachment = $a->get($_GET['id']);
//filename will be original file name with user name.n prepended
$fileName = $attachmentPath.$_SESSION['nameN'].'-'.$attachment->file_name;
//instantiate new attachmentDownload and query for attachment chunks
$a = new AttachmentDownload();
$chunks= $a->getRecords(array('sys_attachment'=>$_GET['id'], '__order_by'=>'position'));
$fh = fopen($fileName.'.gz','w');
// read and base64 encode file contents
foreach($chunks as $chunk){
fwrite($fh, base64_decode($chunk->data));
}
fclose($fh);
//open up filename for writing
$fh = fopen($fileName,'w');
//open up filename.gz for extraction
$zd = gzopen($fileName.'.gz', "r");
//iterate over file and write contents
while (!feof($zd)) {
fwrite($fh, gzread($zd, 60*57));
}
fclose($fh);
gzclose($zd);
unlink($fileName.'.gz');
$info = pathinfo($fileName);
header('Content-Description: File Transfer');
header('Content-Type: '.Mimetypes::get($info['extension']));
header('Content-Disposition: attachment; filename=' . basename($fileName));
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($fileName));
ob_clean();
flush();
readfile($fileName);
exit();
}else{
header("location: ".$links['status']."?".urlencode("item=incident&action=view&status=-1&place=".$links['home']));
}
?>
This results in sending me the file, but when I open it I receive an error saying:
"File type plain text document (text/plain) is not supported"
First off, I'd start by checking the HTTP headers. You can do this in Firefox easily using the "Live HTTP headers" extension; not sure about equivalents in other browsers offhand. This will let you verify if the header is actually getting set to "application/pdf" and whether your other headers are getting set as well.
If none of the headers are getting set, you might be inadvertently sending output before the calls to header(). Is there any whitespace before the <?php tag?
Are you sure application/pdf is the header your browser is actually seeing?
You can check that out with various HTTP dev tools, for instance HTTP Client for the Mac or Firebug for Firefox.
I use this one and it works.
if(file_exists($file_serverfullpath))
{
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
//sending download file
header("Content-Type: application/octet-stream"); //application/octet-stream is more generic it works because in now days browsers are able to detect file anyway
header("Content-Disposition: attachment; filename=\"" . basename($file_serverfullpath) . "\""); //ok
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($file_serverfullpath)); //ok
readfile($file_serverfullpath);
}
Try prepending "error_reporting(0);". I found this in the comments at http://php.net/readfile (where you took this example from).
Another thing that could be a problem is your file size. There have been issues reported in the past about PHP5 (we're talking 2005 here, so i hope this is fixed by now) having trouble reading files >2MB. If your file size exceeds this you may want to verify that it reads the whole file.

Php downloading all file types

i am just wondering if there is a way of setting up different "content-type" when downloading through php? like .mp3 AND .pdf etc.. instead of having to specify just one file type. My problem is that i have 2 file types to be downloaded, one type is pdf and the other type is mp3, but if i change the "content-type" to audio/mpeg, then it doesn't show the extension for the .pdf... i hope you understand? please help!
If you mean your user is downloading some content that's sent from a PHP script, which is also sending the Content-type HTTP header, can you not set that header with a different value for each type of file ?
Something like this (pseudo-code) :
if (file is a PDF) {
header('Content-type: application/pdf');
} else if (file is a MP3) {
header('Content-type: audio/mpeg');
}
And a "default" case might be useful, if you also have some other files you have not thought about just yet.
This function works great for me:
function Download($path, $speed = null)
{
if (is_file($path) === true)
{
set_time_limit(0);
while (ob_get_level() > 0)
{
ob_end_clean();
}
$size = sprintf('%u', filesize($path));
$speed = (is_null($speed) === true) ? $size : intval($speed) * 1024;
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: ' . $size);
header('Content-Disposition: attachment; filename="' . basename($path) . '"');
header('Content-Transfer-Encoding: binary');
for ($i = 0; $i <= $size; $i = $i + $speed)
{
echo file_get_contents($path, false, null, $i, $speed);
while (ob_get_level() > 0)
{
ob_end_clean();
}
flush();
sleep(1);
}
exit();
}
return false;
}
You can also optionally specify the max speed at which the file is delivered.

How do I put a download button on a site to get a CSV of a table Query?

How do I put a download button on a site to get a CSV of a table Query?
Currently I am using SELECT * INTO OUTFILE to make the CSV file on the server HD and is fine except...
I want to create the CSV like I am now, but I want the "OUTFILE" to be saved on the clients computer when they click Download.
<?php
// Create new file name for file to be created
$csvfilename = "/dropbox/consolodated-" . date("Y-M-d_H-i-s") . ".csv";
mysql_query ("SELECT * INTO OUTFILE '$csvfilename' FIELDS TERMINATED BY ',' FROM people ");
?>
<H2>Done - File created - Now download it from FTP site.</H2>
The solution to this can be that:
First you save the csv file on to server.
then get it's path
and finally create an anchor tag with its path for download eg:
_
Download
Here are a couple of similar posts:
Generating CSV file and then forcing the file to download.
PHP code to convert a MySQL query to CSV
Add a POST form at the end which includes a hidden field containing the filename (but NOT the path!) of the file to download. Then have the page it POSTs to read the variable and offer the file for download. Don't forget to enable output buffering and to occasionally flush so that the form is not visible until the query has completed.
Simple, here is a sample snippet:
$csv_filename = "/dropbox/consolodated-" . date("Y-M-d_H-i-s") . ".csv";
Download($csv_filename);
And here is the download function:
function Download($path, $speed = null)
{
if (is_file($path) === true)
{
set_time_limit(0);
while (ob_get_level() > 0)
{
ob_end_clean();
}
$size = sprintf('%u', filesize($path));
$speed = (is_null($speed) === true) ? $size : intval($speed) * 1024;
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: ' . $size);
header('Content-Disposition: attachment; filename="' . basename($path) . '"');
header('Content-Transfer-Encoding: binary');
for ($i = 0; $i <= $size; $i = $i + $speed)
{
echo file_get_contents($path, false, null, $i, $speed);
flush();
sleep(1);
}
exit();
}
return false;
}
Merry Xmas to you too! =)

Categories