PHP File creation and download on the fly - php

Hey guys I was wondering how I could download a file that is generated on the fly by PHP. The file I want to download would be an XML file. At the moment all my code does is create a long string with all of the data that is to put in the file, it then simply writes the string to a file and saves it with a .XML extension. This is currently working in my local machine using a copy of the website, it won't work on the web server though due to read/write permissions.
So is there a way to generate a file in the fly to be immediately downloaded without storing it on the web server?

If the same script is generating the file, you could echo or print the contents on to the page and use header to force download.
<?php
header('Content-type: text/xml');
header('Content-Disposition: attachment; filename="file.xml"');
echo $XMLString;
?>
And if you have a different file for downloading the file, just use file_get_contents and output the file data!
That should do you :)

Just give these two things on the top of the document:
<?php
header('Content-type: text/xml');
header('Content-Disposition: attachment; filename="myxml.xml"');
?>

Related

PHP file download with no changes to the file

I am trying to make a file download by using PHP but the file downloaded is a clean mp3 file without tags/metadata and not the one that is on my server.
Here's a detailed explanation:
I have a mp3 file with saved ID3 tags and all information on my server.
I run this code to start the download:
header('Content-Type: application/mp3');
header('Content-Disposition: attachment; filename="file.mp3"');
header('Pragma: no-cache');
readfile("file.mp3");
This starts a file download, but the file that is downloaded loses all its meta data, including any info and album art. Is there a way around this?
For example opening the file url and right clicking -> Save As, downloads it and preserves all the information stored in the file.
How can I prevent the deletion of all the metadata? Thanks for your help
Just add these two lines:
ob_end_clean();
flush();
readfile("file.mp3");

PHP Force Download - Limit possible file download

I'm using the following to force download of MP3 files:
http://www.aaronfagan.ca/blog/2014/how-to-use-php-to-force-a-file-download/
Basically using PHP lines to force a download
<?php
if ($_GET['id']) {
$file = $_GET['id'];
header("Content-Description: File Transfer");
header("Content-Type: application/octet-stream");
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header("Content-Length: ".filesize($file));
readfile($file);
}
else {
header('Location: http://www.mywebsite.com/error/');
}
?>
Am I correct to understand that anyone that knows how it works could basically download any files on any website with this?
For example, if I place that file in the root of mywebsite.com, anyone with knowledge could use a link like the following to download any file anywhere?:
http://www.mywebsite.com/download.php?id=http://www.anywebsite/files/file.pdf
Or would it only work on my website?
The files I want users to be able to download are MP3 files, would there be a way to "restrict" the type of files the "download.php" would process? so this way the "Content-Type" be set to something for only MP3 files, this way the "hack" would be restricted?
For example if I place that file in the root of mywebsite.com, anyone
with knowledge could use a link like the following to download any
file anywhere?:
http://www.mywebsite.com/download.php?id=http://www.anywebsite/files/file.pdf
If permissions open for http://www.anywebsite/files/file.pdf (it means you can open/download file.pdf with browser) you can download it remotly with your script (but as I now basename uses for local paths),
but usually permissions denied for direct download (you can close permissions too).
Also if you want you can add captcha to your download method to disable grab
Thanks.
Your code works only on your website.
For serving resources from other servers you can use this script Resource-Proxy.
Good Luck

Forcing file to download in CodeIgniter FTP class

I am using the FTP class in CodeIgniter, they have a function for downloading the file from the FTP, however, its only to the server itself. I am trying to get it to download straight to the user.
I know that i could just save it to the server and then force download and then delete. But its a bit of a hassle if the file is large and it would be slow.
So i am wondering from this code, if there is anyway just to use the force_download CI function?
Example;
$this->ftp->download('/public_html/myfile.html', '/local/path/to/myfile.html', 'ascii');
Thanks!
You simply download the file to PHP's standard output stream instead of a file [stream] like so:
<?php
header('Content-type: text/plain');
header('Content-Disposition: attachment; filename="test.txt"');
$this->ftp->download('/public_html/test.txt', 'php://output', 'ascii');
(Note: headers are used to force the download, otherwise the browser would simply print the contents)
You're welcome!

Opening downloaded zip file creates cpgz file?

If I make the url for a zip file the href of a link and click the link, my zip file gets downloaded and opening it gets the contents as I expect.
Here's that HTML:
download zip
The problem is I'd like the link to point to my application such that I could determine whether the user is authorized to access this zip file.
so I'd like my HTML to be this:
download zip
and my PHP for the /canDownload page:
//business logic to determine if user can download
if($yesCanDownload){
$archive='https://mysite.com/uploads/my-archive.zip';
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=".basename($archive));
header("Content-Length: ".filesize($archive));
ob_clean();
flush();
echo readfile("$archive");
}
So, I think the problem has to do with the header() code but i've tried a bunch of things related to that based on various google and other SO suggestions and none work.
If you answer my question, it is likely you can answer this question too: Zipped file with PHP results in cpgz file after extraction
The answer in my case was that there was an empty line being output before readfile().
So i added:
ob_end_clean();
readfile($filename);
But you should probably search for the place where this line is being output in your code.
The PHP documentation for readfile says that it will output the contents of a file and return an int.
So your code, echo readfile("$archive");, will echo $archive (btw, the double quotes are meaningless here; you should remove them), and THEN output the int that is being returned. That is, your line should be: readfile($archive);
Also, you should be using a local path (not an http:// link) to the archive.
Altogether:
if($yesCanDownload){
$archive='/path/to/my-archive.zip';
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=".basename($archive));
header("Content-Length: ".filesize($archive));
ob_clean();
flush();
readfile($archive);
}
Lastly, if that does not work, make sure filesize($archive) is returning the accurate length of the file.
Ok, I answered my own question.
The main problem, which I originally didn't make clear, was that the file was not located on my application server. It was in a Amazon AWS s3 bucket. That is why I had used a full url in my question, http://mysite... and not just a file path on the server. As it turns out fopen() can open urls (all s3 bucket "objects", a.k.a. files, have urls) so that is what I did.
Here's my final code:
$zip= "http://mysite.com/uploads/my-archive.zip"; // my Amazon AWS s3 url
header("Content-Type: archive/zip"); // works with "application/zip" too
header("Content-Disposition: attachment; filename='my-archive.zip"); // what you want to call the downloaded zip file, can be different from what is in the s3 bucket
$zip = fopen($zip,"r"); // open the zip file
echo fpassthru($zip); // deliver the zip file
exit(); //non-essential
Another possible answer, I found After much searching, I found that the two possible reasons for a *.zip "unzipping" to a *.zip.cpgz are:
the *.zip file is corrupted
the "unzip" tool being used can't
handle >2GB files
Being a Mac user, the second reason was the cause for my problem unzipping the file: the standard Mac OS tool is Archive Utility, and it apparently can't handle >2GB files. (The file in question for me was a zipped 4GB raspbian disk image.)
What I ended up doing was to use a Debian virtual machine, already existing in Virtual Box on my Mac. unzip 6.0 on Debian 8.2 had no problem unzipping the archive.
You're passing the URL to readfile() like:
$archive = 'https://mysite.com/uploads/my-archive.zip';
While you should pass the path on the server, for example:
$archive = '/uploads/my-archive.zip';
Assuming the file is located in the upload folder.
Additionally try the following headers:
header("Content-type: application/octet-stream");
header("Content-disposition: attachment; filename=file.zip");
In my case, I was trying to create the file in a directory above public_html and the rules of the hosting didn't allow it.

PHP - Opening uploaded DOCX files with the correct MIME TYPE

I have users uploading DOCX files which I make available for download. The issues we have been experiencing is the unknown mime types of DOCX files which causes IE to open these docs as Zip files.
It is running on a Windows/IIS server.
Because this is a shared host, I cannot change any server settings.
I was thinking that I could just write some code that would handle DOCX files, perhaps custom output:
if (extension=docx) {
header("Content-Disposition: attachment; etc)
header('Content-Type: application/application/vnd.openxmlformats-officedocument.wordprocessingml.document');
//Output the file contents etc
}
Would this be a viable solution?? If so, can someone help fill in the gaps?
(PS I know the above syntax is not correct, just a quick example)
This should do it:
header('Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
header('Content-Disposition: attachment; filename="myfile.docx"');
readfile('myfile.docx');
Yes, that will work fine. The PHP docs have basically the exact code you want.

Categories