I have some problems with sending files with PHP. I would like to send a file named .version (Note the dot and nothing infort of it). The file is sent correctly but my browser renames it to version. Therefore the file looses its functionality. The file has to be named like this.
This is the code I use:
<?php
header("Content-Description: File Transfer");
header("Content-Type: text/version");
header("Content-Disposition: attachment; filename=\".version\"");
header("Content-Length: " . filesize($file));
readfile($file);
exit();
?>
$file is the correct internal path to the file.
Other headers like the expires header are set in my server config.
If there is information missing I will add if if you ask for it!
Related
The end goal is for the user to download a .csv file. Right now I'm just testing trying to download a simple text file: test.txt. The only thing in this file is the word "test".
Here is the HTML code for files_to_download.php
Test file: <a href='test.php?file=test.txt'>Test.txt</a>
Code for test.php:
if(!(empty($_GET["file"])))
{
$file_name = $_GET["file"];
$path = "path/to/file";
$fullPath = $path . $file_name;
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: inline; attachment; filename=\"$file_name\"");
header("Content-Type: text/plain");
header("Content-Transfer-Encoding: binary");
readfile($fullPath);
}
I've tried variations of the headers above, adding more and removing others. The above seem to be the most common recommended on this site.
I've also tried changing
header("Content-Type: text/plain");
to
header("Content-Type: text/csv");
and get same results: empty .txt or .csv file.
The files are not empty when I open them directly (file browser) from the server. I've checked the permissions of the files and they're both 644, so the entire world can at least read the files. The directory is 777.
Is there a configuration on the Apache server I need to specify that may not be or am I missing something above.
Thanks for looking!
In most cases the path is wrong
Read the text file, then echo the text out after your header() calls.
Here's how I have my csv download set up:
//downloads an export of the user DB
$csv = User::exportUsers();
header('Content-disposition: attachment; filename=userdb.csv');
header('Content-type: text/csv');
echo $csv;
Where exportUsers() creates the csv data. You can easily just replace $csv with the contents of your text file, then echo it out.
And as far as your text file, you can use file_get_contents() to get the contents of your file into a string. Then echo that string.
Try setting the content length of the file:
header('Content-Length: ' . filesize($file));
Also, please have this in mind: file inclusion
In my case, the path was correct. And the download-forcing was working on windows, but not mac.
I figured out after few tests that the header Content-Length was failing. I was using the function filesize on a full url, like :
$url_my_file = "http://my-website.com/folders/file.ext";
header('Content-Length: '.(filesize($url_my_file)));
I replace it by
$url_my_file = "http://my-website.com/folders/file.ext";
$headers = get_headers($url_my_file, 1);
header('Content-Length: '.($headers['Content-Length']));
And ... It's working now :)
I'm having trouble with downloading a file from a hashed filepath.
I'm using a MySQL database where I store various data from a HTML form. It is possible to upload up to three different files. These are moved to a uploads folder on the server. I’m using MD5 to prevent duplicate file uploads.
All the data in the database gets called from an other script. There is an amount of download links shown, depending on how much files are uploaded. Im using fileinfo and headers to determine the mimetype and to download the file. But all I get when downloading is some zipfile with random folders and documents or a non-extension file which, giving the right extension, opens with warnings and ultimately shows the correct file.
Here is my download code:
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
print("</br>"); echo finfo_file($finfo, $_GET["fName"]);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename= ". $_GET["fName"]);
header("Content-Type: " .$finfo);
finfo_close($finfo);
header("Content-Transfer-Encoding: binary");
// Read the file from disk
readfile($_GET["fName"]);
The $_GET["fName"] is a variable passed by a link which contains the specified pathname(example: ./uploads/hashcode). How can I make this so that I can download the document correctly? As in download the document whole, not some ZIP file or a non-extension file.
I’ve been fighting with this problem for some days now (searched on internet to find something usable) and im getting quite desperate.
Additional note: Most times the file that downloads is the correct file from my server. It has the same name as the hash files in the uploads folder. But it doesnt have any extension.
Let's say $_GET["fName"] is /uploads/randomhash/ABCDEFABCDEFABCDEF.zip
header("Content-Disposition: attachment; filename= ". basename($_GET["fName"]));
This would make the server to name downloadable file as ABCDEFABCDEFABCDEF.zip
If you have saved your files without extension, then you might have a problem.
If you have the orginal filename saved in database maybe you could add extra $_GET['orginalFilename'] to your links and use that to generate right filename with extension.
Also you are setting headers. They aren't being set correctly if you output anything before them. Here you print and finfo_file. You shouldn't do that.
I think you want something like this, but you have to figure out how to get right filename to the filename= part in header.
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename= ". basename($_GET["fName"]));
header("Content-Type: " . finfo_file($finfo, $_GET["fName"]));
finfo_close($finfo);
header("Content-Transfer-Encoding: binary");*/
// Read the file from disk
readfile($_GET["fName"]);
I use this code to enable users to download a zip file:
if(file_exists($filename)){
header("Content-Disposition: attachment; filename=".basename(str_replace(' ', '_', $filename)));
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . filesize($filename));
flush();
$fp = fopen($filename, "r");
while (!feof($fp))
{
echo fread($fp, 65536);
flush();
}
fclose($fp);
exit;
}
When the file is downloaded, it only downloads 25,632 kilobytes of data. However the zip file is 26,252 kilobytes ...
Why does the browser get all 25MB but then stop?
I checked the Content-Length header to make sure it was correct and it is...
edit
In firefox, when i download the file, it says 'of 25mb' SO the browser thinks that 25mb is the COMPLETE amount... however, the content-length when echo'd is 26252904?
add this before your code
ob_clean();
ob_end_flush();
Your header('Content-Type ...) calls are useless as only the last one will be sent to the browser.
Downloads are triggered by Content-Disposition: attachment. You should send the actual Content-Type: application/zip if you are sending a zip file.
Finally, your read loop is unnecessary.
Putting it all together, your code should look like this:
if (file_exists($filename)) {
$quoted_filename = basename(addcslashes($filename, "\0..\37\"\177"));
header("Content-Disposition: attachment; filename=\"{$quoted_filename}\"");
header('Content-Type: application/zip');
header('Content-Length: '.filesize($filename));
readfile($filename);
}
Use a single MIME type to represent the data.
In this case using application/octet-stream will do just fine. This is when you dont know the MIME before hand. When you know it, you must put it. Do not use multiple content-type headers.
Usually, when the browser doesn't know how to handle a particular MIME, it will trigger the download process. Further, using Content-disposition: Attachment; .. ensures it.
There exists a simple readfile($filename) which will send out the bytes of the file to the requesting process like below:
header("Content-disposition: attachment;filename=" . basename($filename);
readfile($filename);
I had similar problem. The file downloaded fine in Firefox but not in IE. It appeared that Apache was gzipping the files and IE was not able to ungzip so the files were corrupted. The solution was to disable gzipping in Apache. You can also check if PHP is not gzipping on the fly and disable it too.
For Apache you can try:
SetEnv no-gzip 1
And for PHP, in .htaccess:
php_flag zlib.output_compression on
This answer is by No means a REAL ANSWER.
However i did get it to work... I just set the Content-Length to 30000000. Therefor it thinks the file is bigger than it actually is, and then it downloads it all.
Ugly hack i know, but i couldn't find ANY other way
The end goal is for the user to download a .csv file. Right now I'm just testing trying to download a simple text file: test.txt. The only thing in this file is the word "test".
Here is the HTML code for files_to_download.php
Test file: <a href='test.php?file=test.txt'>Test.txt</a>
Code for test.php:
if(!(empty($_GET["file"])))
{
$file_name = $_GET["file"];
$path = "path/to/file";
$fullPath = $path . $file_name;
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: inline; attachment; filename=\"$file_name\"");
header("Content-Type: text/plain");
header("Content-Transfer-Encoding: binary");
readfile($fullPath);
}
I've tried variations of the headers above, adding more and removing others. The above seem to be the most common recommended on this site.
I've also tried changing
header("Content-Type: text/plain");
to
header("Content-Type: text/csv");
and get same results: empty .txt or .csv file.
The files are not empty when I open them directly (file browser) from the server. I've checked the permissions of the files and they're both 644, so the entire world can at least read the files. The directory is 777.
Is there a configuration on the Apache server I need to specify that may not be or am I missing something above.
Thanks for looking!
In most cases the path is wrong
Read the text file, then echo the text out after your header() calls.
Here's how I have my csv download set up:
//downloads an export of the user DB
$csv = User::exportUsers();
header('Content-disposition: attachment; filename=userdb.csv');
header('Content-type: text/csv');
echo $csv;
Where exportUsers() creates the csv data. You can easily just replace $csv with the contents of your text file, then echo it out.
And as far as your text file, you can use file_get_contents() to get the contents of your file into a string. Then echo that string.
Try setting the content length of the file:
header('Content-Length: ' . filesize($file));
Also, please have this in mind: file inclusion
In my case, the path was correct. And the download-forcing was working on windows, but not mac.
I figured out after few tests that the header Content-Length was failing. I was using the function filesize on a full url, like :
$url_my_file = "http://my-website.com/folders/file.ext";
header('Content-Length: '.(filesize($url_my_file)));
I replace it by
$url_my_file = "http://my-website.com/folders/file.ext";
$headers = get_headers($url_my_file, 1);
header('Content-Length: '.($headers['Content-Length']));
And ... It's working now :)
i'm trying to create downloadable video-files. In my site there is a list of files.
All videos are in .flv-format (flash). There is exact link to the file for the all videos.
But in all browsers after clicking content is loading to the browser`s window. I needn't in this. As i understand i should create redirect-page wich contains mime-type of the download file. What exactly should i do?
Language: php
The recommended MIME type for that is application/octet-stream:
The "octet-stream" subtype is used to indicate that a body contains arbitrary binary data. […]
The recommended action for an implementation that receives an "application/octet-stream" entity is to simply offer to put the data in a file, with any Content-Transfer-Encoding undone, or perhaps to use it as input to a user-specified process.
Create a PHP page with the following:
<?php
$filepath = "path/to/file.ext";
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$filepath");
header("Content-Type: mime/type");
header("Content-Transfer-Encoding: binary");
// UPDATE: Add the below line to show file size during download.
header('Content-Length: ' . filesize($filepath));
readfile($filepath);
?>
Set $filepath to the path of the file to be downloaded, and set Content-Type to the mime type of the file being downloaded.
Point the "download" link to this page.
For multiple files of the same type:
<?php
$filepath = $_GET['filepath'];
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$filepath");
header("Content-Type: mime/type");
header("Content-Transfer-Encoding: binary");
// UPDATE: Add the below line to show file size during download.
header('Content-Length: ' . filesize($filepath));
readfile($filepath);
?>
Replace the information as specified above, and point the "download" link to this page with a GET parameter named "filepath" containing the file path.
For example, if you name this php file "download.php", point the download link for a file named "movie.mov" (in the same directory as download.php) to "download.php?filepath=movie.mov".