how to access file from outside root directory in php - php

I have a code to download zip files:
$dl_path = './';
$filename = 'favi.zip';
$file = $dl_path.$filename;
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/zips');
header("Pragma: public");
header("Expires: 0");
header("Cache-Control:must-revalidate, post-check=0, pre-check=0");
header("Content-Type:application/force-download");
header("Content-Type:application/download");
header("Content-Disposition:attachment;filename=$filename ");
header("Content-Transfer-Encoding:binary ");
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
there is root directory /public_html, the script is executing in root directory.
there is zip file in / directory.
i am trying to use the $dl_path as / but it is not working.
Please help.

$dl_path = __DIR__.'/..'; // parent folder of this script
$filename = 'favi.zip';
$file = $dl_path . DIRECTORY_SEPARATOR . $filename;
// Does the file exist?
if(!is_file($file)){
header("{$_SERVER['SERVER_PROTOCOL']} 404 Not Found");
header("Status: 404 Not Found");
echo 'File not found!';
die;
}
// Is it readable?
if(!is_readable($file)){
header("{$_SERVER['SERVER_PROTOCOL']} 403 Forbidden");
header("Status: 403 Forbidden");
echo 'File not accessible!';
die;
}
// We are good to go!
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header("Pragma: public");
header("Expires: 0");
header("Cache-Control:must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/download");
header("Content-Disposition: attachment;filename={$filename}");
header("Content-Transfer-Encoding: binary ");
header('Content-Length: ' . filesize($file));
while(ob_get_level()) ob_end_clean();
flush();
readfile($file);
die;
^ try this code. See if it works. If it doesn't:
If it 404's means the file is not found.
If it 403's it means you can't access it (permissions issue).

First of all check if your script is running under the correct directory by echoing dirname(__FILE__).
If it is running under public_html then you can change the code like this:
$dl = dirname(__FILE__). '/../';
But beware of security issue!
Check if you have read/write permission on the file and directory
Check the open_basedir restriction in php.ini (see How can I relax PHP's open_basedir restriction?)
Hope this helps

Related

PHP says file does not exists when it does

Very lost right now. The filePath to this document is correct and is in the directory that is being printed by the echo but it keeps saying "file not found".
$fileName = 'driver.txt';
$filePath = $_SERVER['DOCUMENT_ROOT']."/driver.txt";
echo $filePath;
if(!file_exists($filePath)){ // file does not exist
die('file not found');
} else {
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$fileName");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
// read the file from disk
readfile($filePath);
}
Very silly mistake, tried downloading a different file and it worked. I then realized the file's name was driver.txt. So PHP was looking for driver.txt.txt. I appreciate all the help.

Php or Apache? Content of zip file is diplayed instead of downloading zip file

I tried to write a php-script to create and download a zip file. When I tested the script on my localhost, the download works, but when it's uploaded to the server, things go wrong: instead of downloading the zip file, the content of the file is displayed in the browser.
Can somebody point me in the right direction?
The code
$zip = new ZipArchive();
$zip->open("$maand/zipfile.zip", ZipArchive::OVERWRITE);
$zip->addFile("$maand/ant/a_nb.txt", 'ant.txt');
$zip->addFile("$maand/lim/l_nb.txt", 'lim.txt');
$zip->addFile("$maand/oos/o_nb.txt", 'oos.txt');
$zip->addFile("$maand/vla/v_nb.txt", 'vla.txt');
$zip->addFile("$maand/wes/w_nb.txt", 'wes.txt');
$zip->close();
$filename = "zipfile.zip";
$filepath = "$maand/";
// headers for zip downloads
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
header("Content-Length: ".filesize($filepath.$filename));
ob_end_flush();
#readfile($filepath.$filename);
you missing ob_start()
example:
header('Content-Type: application/csv');
header('Content-Disposition: attachement; filename="' . $download . '"');
ob_start();
$str = '';
if(file_exists($file) === true){
$str = file_get_contents($file);
}
ob_end_clean();
echo $str;

Forcing php to download a file inside zip

I have a file image.php that dynamically views an image inside a Zip folder.
So image.php?location=./folder/Hi.zip&file=image.jpg views the image.
I have another file downloadfile.php that forces download of file specified in the parametes.
downloadfile.php?location=.folder/&file=image.jpg* downloads the image*
What I need is to download the dynamically generated image (by image.php) using downloadfile.php.
downloadfile.php
<?php
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
$file=$_GET['file'];$ext=$_GET['ext'];$location=$_GET['location'];
header('Content-disposition: attachment; filename="'.$file.'"');
header('Content-type:"'.$ext.'"');
readfile("$location"."$file");
?>
image.php
<?php
function showimage($zip_file,$file_name)
{
$z=new ZipArchive();
if($z->open($zip_file)!=true){
echo "File not found";
return false;
}
$stat=$z->statName($file_name);
$fp=$z->getStream($file_name);
if(!$fp){
echo "Could not load image";
return false;
}
header('Content-Type:image/'.$_GET['type']);
header('Content-Length:'. $stat['size']);
fpassthru($fp);
return true;
}
showimage($_GET['zip'],$_GET['file']);
?>
Any suggestions??
In order to force browser to download an image file you can use the code from image.php
and just change the header
from
header('Content-Type:image/'.$_GET['type']);
header('Content-Length:'. $stat['size']);
to
header("Content-Transfer-Encoding: binary");
header('Content-Description: File Transfer');
header('Content-Type:image/'.$_GET['type']);
header('Content-Length: ' . $stat['size']);
header('Content-Disposition: attachment; filename=' . $file_name);
this will force user to download instead of display an image.

Php: Keep same filename when downloading from server

I'm downloading a file through php script and everything work perfectly except one ugly truth. The downloaded file keep the same url and with original name appended. How do I maintain the same filename when file downloaded?
http://bachday.com/index.php?page=custom&file=mmailer/download.php?mfile=sample.docx
if (isset($_GET['mfile'])) {
$file = $_SERVER['DOCUMENT_ROOT'].'/oc-content/plugins/mmailer/pfile/'.$_GET['mfile'];
if (file_exists($file) && is_readable($file) && preg_match('/\.docx$/',$file)) {
header('Content-Type: application/docx');
header("Content-Disposition: attachment; filename=\"$file\"");
readfile($file);
/*
header("Expires: 0");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
echo (readfile($file));*/
}
else
{
header("HTTP/1.0 404 Not Found");
echo "Error 404: File Not Found: $file";
}
header('Content-Disposition: attachment; filename="name_of_file_here"') would have done the trick. You are passing the full path of the file there as header("Content-Disposition: attachment; filename=\"$file\""); since your $file contains full path. Instead just send the name of the file.
header('Content-Disposition: attachment; filename='.basename($file));
This line can perhaps solve the issue.
if (isset($_GET['mfile'])) {
$file = $_SERVER['DOCUMENT_ROOT'].'/oc-content/plugins/mmailer/pfile/'.$_GET['mfile'];
if (file_exists($file) && is_readable($file) && preg_match('/\.docx$/',$file)) {
header('Content-Type: application/docx');
header("Content-Disposition: attachment; filename=\"".basename($file)."\"");//use basename to extract filename from full file path
readfile($file);
/*
header("Expires: 0");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
echo (readfile($file));*/
}
else
{
header("HTTP/1.0 404 Not Found");
echo "Error 404: File Not Found:
$file";
}

PHP downloads at 0 bytes

I have ZIP files in a directory that is one step up from the root directory (to prevent hotlinking etc...). Here is the code:
<?php
$filename = $_GET['id'];
if(!$filename){
header("Location: index.html");
} else {
function send_download($filename){
$file_path = '../../../../downloads/' . $filename . '.zip';
$file_size=#filesize($file_path);
header("Content-Type: application/x-zip-compressed");
header("Content-disposition: attachment; filename=$filename");
header("Content-Length: $file_size");
readfile($file_path);
exit;
}
send_download($filename);
}
?>
All the ZIP files are fine but using this method on an 'a' tag causes the downloads to be 0 bytes in file size! :(
Any ideas as to why?
Many thanks!
Can you try changing the Content-type to the following:
Content-type: application/x-zip;
And before you do, check if the file exists.
<?php
$filename = $_GET['id'];
if(!$filename){
header("Location: index.html");
} else{
function send_download($filename){
$file_path = '../../../../downloads/' . $filename . '.zip';
if (file_exists($file_path))
{
$file_size=#filesize($file_path);
header("Content-Type: application/x-zip-compressed");
header("Content-disposition: attachment; filename=$filename");
header("Content-Length: $file_size");
readfile($file_path);
exit;
}
send_download($filename);
}
else
die("Error 404!");
}
?>
header("Location: http://www.fqdn.tld/file.ext");
Based on _GET["id"] being > 0 and not null, you've created a function which has been used directly after, so you've just added more lines of code for no required purpose.
I see you have added an "#" sign as people have previously commented, however, the only way for you to begin fixing this is by:
Removing the # sign as you should never use it, very bad practice, you should cater for all exceptions in your code, it makes for a really good programmer. (Scripting in PHP)
error_reporting(E_ALL);
Place point b) on it's own line but after the <?php - so we can see a full list of errors.
Your code is fine, the problem you have is permissions, ensure that apache has access to your "files" repository, the fact you are able to check that the file is there suggest slight permissions and the files exists, the point that 0 bytes are being returned suggest reading privileges are denied at Apache level.
Right, after a bit of Googling and some blood, sweat and tears I have finally found a solution!
<?php
$filename = $_GET['id'];
header('Content-type: application/zip');
header("Content-Disposition: attachment; filename=" . $filename);
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
readfile('../../downloads/' . $filename . ".zip");
exit;
?>
Many thanks to all of whom shed some light on this!
And here is the code with the filesize:
<?php
$filename = $_GET['id'];
$file = "../../downloads/" . $filename . ".zip";
header('Content-type: application/zip');
header("Content-Disposition: attachment; filename=" . $file);
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-length: " . filesize($file));
readfile($file);
//echo filesize($file);
exit;
?>
Only one mistake we all are doing check below.
readfile($file); //$file should be relative not absolute. That's it.
Thanks,
Anirudh Sood.

Categories