I have a page with mp3s that are playable from a player, and there are also links to download the songs. When the user clicks on the download link, it needs to open the download dialog instead of opening a media player, so it was recommended to me to use this header script:
includes/auto-download.php:
<?php
$path = $_GET['path'];
header('Content-Disposition: attachment; filename=' . basename($path));
readfile($path);
?>
And then on my main page, the link looks like this:
Song Name
I seem to be doing something wrong with my paths, as when I click the link, the download box opens, and I can download a file with the correct name, but it doesn't contain any information.
To elaborate on my file structure, I've got this:
/Patrons (where my main index.php page is with my link
/Patrons/includes (where my auto-download.php script is)
/Patrons/Media/Audio/Date/ (this is where all the songs are)
Any help would be greatly appreciated!
Either change HTML code to this:
Song Name
OR change PHP code to this:
readfile('../'.$path);
$path needs to be the relative path to the file from the web root. with no leading slash. If the files are outside the web root you should use a fullpath (/home/webuser/song_files/song.mp3).
For example $path = 'song_files/'. $_GET['name_of_the_file'];
You should also check if the file does not exist and exit with an error.
Here is an example I made in codeigniter.
function _begin_download($document_data) {
basepath = 'uploads/';
$filepath = basepath . $document_data->filename;
if (file_exists($filepath)) {
header("Content-type: " . $document_data->mimetype);
header("Content-length: " . filesize($filepath));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-disposition: attachment; filename="' . $document_data->filename . '"');
readfile($filepath);
exit();
} else {
exit('File not found.');
}
}
Related
I want to download image file in php.
<?php
if(isset($_REQUEST["file"])){
$filepath = BASE_URL.'assets/uploads/save_template_images/template1_221594899972.png';
// Process download
if(file_exists($filepath)) {
echo $filepath;
exit;
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
flush(); // Flush system output buffer
readfile($filepath);
die();
} else {
echo $filepath;
exit;
http_response_code(404);
die();
}
}
?>
In my index page, I have an anchor tag and if click on anchor tag then above code run. I am not showing anchor tag because, I put the $filepath static value in above code. When I run above code then it goes on else condition. I think, full path of project is not taking by above code. If I put image in same folder then it downloads.
First ensure allow_url_fopen setting in php.ini file is turned on. After that Use this code to download your file:
<?php
$url = 'https://lokeshdhakar.com/projects/lightbox2/images/image-5.jpg';
$file = './files/'.basename($url);
file_put_contents($file, file_get_contents($url));
?>
For successful download, files directory must be exists. But I think it would be inefficient to add directory existence check as I think you already know where to save the file you are downloading.
File links are all http://website.com/f/xxx.png/zip/txt and so on.
I need to set it up so that if a user downloads that file it would download with a different name.
I have seen how to do this on a normal page, but I have no clue how making it work when the image itself is linked to is done.
Appreciate any help :)
Edit: Using the rewrite Steven Jeffries posted,
header('Content-Disposition: inline; filename=' . $originalFileName . "'");
header("Content-Type:" . $mimeType);
$im = imagecreatefrompng($filePathOnServer);
imagepng($im);
to display images and
header('Content-Disposition: attachment; filename=' . $originalFileName . "'");
header("Content-Type:" . $mimeType);
to make other files download solved the issues I had.
I think an easy way to do this would be to redirect download links to another script that handles what to download, etc. Basically, I'd set up a download dir, add some rewrite rules, and then create a script to handle what gets output.
Something like this (untested):
/path-to-web-root/download/.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.* /downloads/handle-downloads.php
/path-to-web-root/download/handle-downloads.php
$url = trim($_SERVER['REQUEST_URI'], '/');
if (preg_match('^#downloads/(?<real_filename>.*?)/(?<options>.*)/(?<fake_filename>.*)$#', $url, $matches)) {
// Double check my regex, but basically pull the real filename from the url here
$actual_file = "/path-to-webroot/f/{$matches['real_filename']}";
$options = explode('/', $matches['options']);
if (in_array('zip', $options)) {
// Handle zip, etc.
}
$fake_filename = $matches['fake_filename'];
if (file_exists($actual_file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($fake_filename).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($actual_file));
readfile($file);
exit;
}
}
Then, instead of having the download link being website.com/f/xxx.png/zip/txt, you could instead do website.com/download/xxx.png/zip/txt/new-filename.png. This would allow you to set the filename to whatever you wanted since the browser will just take what's at the end of the url.
Edit: I've included the relevant code from readfile's manual page.
You can set the file response file name by setting header parameter.
For example:
<?php
header('Content-Type: image/png');
header('Content-Disposition: attachment; filename="xyz.png"');
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
...
More on PHP header function here: http://php.net/manual/en/function.header.php
This php file is supposed to:
receive a piece of information from a form on a different page
use this information to create an array of file paths to add to a zip file
create a dynamically named zip file using a class that's included.
force the download of the newly created zip file
numbers 1-3 are working flawlessly.
The page even forces the download of a zip file that is correctly named and is the right size, but when I try to open it, it says the file is invalid. I've seen similar problems in searches, but I have yet to find a solution.
If i enter the direct URL for the newly created zip into the browser, the file downloads and opens perfectly. As a matter of fact, my temporary fix was creating a dynamic direct link to the files :/
I should probably mention that this is hosted on the go daddy economy plan.
<?php
error_reporting(0);
include "gavScripts/connect_to_mysql.php";
require_once 'Zipper.php';
// prepare the file paths to add to the zip file and find the job/client name (for naming the zip folder)
if(isset($_POST['jobName']))
{
$clientID = $_POST['jobName'];
$clientSQL = mysql_query("SELECT clientName FROM job_client WHERE clientID = $clientID");
while($clientRow = mysql_fetch_array($clientSQL))
{
$clientName = $clientRow['clientName'];
}
$zipSQL = mysql_query("SELECT filePath FROM job_expense WHERE clientID = $clientID");
While($zipRow = mysql_fetch_array($zipSQL))
{
$filePaths[] = $zipRow['filePath'];
}
}
//create the zip folder and store the requested files
$zipper = new Zipper();
$zipper->add($filePaths);
$zipper->store('invoices/' . $clientName . '_Invoices.zip');
//download the zip
$fileDownload = 'invoices/' . $clientName . '_Invoices.zip';
$fileName = basename($fileDownload);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=" . $fileName . "");
header("Content-Length: " . filesize($fileDownload));
readfile($fileDownload);
?>
You may have trailing whitespace at the end of your script which is breaking your zip file. Is there a \r or \n (or both) after the closing ?>? Try removing the closing ?> which is optional anyway.
Try the following:
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime($fileName)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="'.basename($fileName).'"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($fileName));
header('Connection: close');
readfile($fileName);
exit();
Might help.
Got a bit of a PHP problem I am stuck on at the moment. I have a file called download.php which gives secure access to file downloads which are stored in a private folder on the server. i.e. 1 level above httpd.
The code looks like this.
$Document = new Documents($DID);
$file = $Document->getfilewithdir();
header("Content-Description: File Transfer");
header("Content-length: " . $Document->getfilesize());
header("Content-type: " . $Document->getfiletype());
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-disposition: attachment; filename=\"" . basename($Document->getfilename()) . "\"");
readfile($file);
exit;
Where
$Document->getfilewithdir() returns something like /Applications/MAMP/htdocs/Portal_QCNW/private/portal_files/filename.docx
and
$Document->getfilename() returns something like filename.docx.
Extra code included:
function setfilename($Val)
{
$this->c_Filename = $Val;
}
function getfilename()
{
return $this->c_Filename;
}
function getfilewithdir()
{
$path_parts = pathinfo($this->geturl());
$file_name = $path_parts['basename'];
return FILELOC . $file_name;
}
This is all fine if there file name has no spaces in, but if there are spaces in the file name i.e. file name.docx or filename (1).docx then the readfile statement returns "failed to open stream". What can I do to get round this and deal with spaces in filenames?
I use https://blueimp.github.io/jQuery-File-Upload/ to upload the file, and there could be something there were I remove spaces at the upload stage.
Any thoughts and advice would be great.
Kind Regards
James
Thanks for your help. I reviewed the code and simplified it. Because I was passing a URL file name it was been formatted as a url rather than a string.
All sorted now.
James
Hello guys i have a problem streaming PDF files with php, i'm using this code:
if(file_exists($path))
{
//octet-stream
header("Content-Length: " . filesize ( $path ) );
header("Content-type: application/octet-stream");
header("Content-disposition: attachment; filename=".basename($path));
readfile($path);
}
This is my directory layout (so you can understand where the PDF are stored):
Parent/
verify.php
auth/
pdf/
login.php
If i stream the a pdf from verify.php all works as intended... but if i stream the SAME PDF file from login.php they are corrupted (damaged).
Here my path definition in login.php
$path = "pdf/" . $filename . "_print.pdf";
And here my path definition in verify.php
$path = "auth/pdf/" . $filename . "_print.pdf";
Obviosly path definition is before che stream code.
The average dimension of pdf files are up to 50Kb.
The file exists beacuse pass the if check but i've no clue about why in one place is ok and in the other is damaged. (i've checked the file into the directory are okay).
Sorry for my poor english and thank you in advance.
i fixed the issue editing the code like this:
header("Content-Length: " . filesize ( $path ) );
header("Content-type: application/octet-stream");
header("Content-disposition: attachment; filename=".basename($path));
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
ob_clean();
flush();
readfile($path);
The path work in both ways: relative or absolute.
Thanks to:
readfile not working properly
Your current working derictory doesn't change depending on your included script path. So if /var/www/parent/auth/login.php is included by /var/www/parent/index.php your working directory will remain /var/www/parent.
The popular way to deal with this is to define a define('BASEPATH', dirname(__FILE__)); (BASEPATH='/var/www/parent') constant in your main file, and use it everywhere else:
//in verify.php
$path = BASEPATH . "/auth/pdf/" . $filename . "_print.pdf";
//in login.php
$path = BASEPATH . "/auth/pdf/" . $filename . "_print.pdf";