PHP force download issue (server config issue) - php

I've created a function to issue a download once user click a link, the file is located in 3rd party storage service (Sugar Sync) and is accessed via their REST API. Now I've created the force download function and tested it runs fine on localhost (a download dialog is prompted), but when I run the function on the server it returns an error page of 'File not Found'. I figured this might be some PHP configuration that needs to be set on server side, but I've got no clue which, so any help or hint is greatly appreciated.
Here's a snippet of the code:
$sugarsync = new SugarSync($refreshtoken);
$response = $sugarsync->get($url);
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: no-cache, must-revalidate");
header("Content-Type: ".$response->mediaType);
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=".$response->displayName.";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$response->size);
//file is returned as binary data from the API
print($sugarsync->download(urldecode($url)));
exit();

As it turns out, after further troubleshooting, the problem is related to output buffering, so I just need to enable that on the server config.

Try adding ob_get_clean(); before your print function like so:
ob_get_clean();
//file is returned as binary data from the API
print($sugarsync->download(urldecode($url)));
exit();

Related

Headers for force download of apk file

I'm doing a script that increases the counter for an APK file's download then sends the file to the browser for download.
Here's what I have:
<?php
$file = "android.apk";
function force_download($file){
header("Pragma: public", true);
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Disposition: attachment; filename=".basename($file));
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($file));
die(file_get_contents($file));
}
force_download($file
The problem is that with a browser like firefox, it downloads but it is like 'android.apk - 0 bytes'. So it essentially, it does not download the file's contents.
What might I be doing wrong? A solution for this?
IMPORTANT: It has to work on mobile.
);
I've never accessed a .apk link that didn't force a download, so I'm not sure what the need for a force download is on that. As far as incrementing the counter, I would probably just link to a page that forwards to the apk file after the counter has been done.
For instance link someone to: getapk.php?apkid=1
Then on getapk.php do something like this:
$update = mysql_query("UPDATE apps SET downloads...");
if ( $update ) { header("Location: appname.apk"); }
Of course that leaves out a lot of details, but if you need help with anything else I'd be happy to provide more details.
I've realized that I don't need to use complex header info expecially if the script will be moved from server to server where the .apk mime type is not native and may therefore be hard for a novice to set up.
A simple redirect will do:
$file_name = $_GET['f']; //$_GET['f'] has the link to the file like http://mydomain.com/file/android.apk
//Do database query or increase download counter
header('location: '.$file_name);
Voila! I have increased the counter and the download will be pushed to the browser.

Retrieving output from a url. How do I force the dowload of a PDF from a url using php

I need to retrieve our reports from the jasperserver report engine as a PDF, then I want the PDF to be forced as a download, instead of being displayed inthe browser. The problem with displaying in the browser is we don't want the report parameters to be displayed to the end users in the url.
If I enter this URL path into the browser I get a PDF document that shows in the same browser window with all the report data:
https://mysite.com:8443/jasperserver/flow.html?_flowId=viewReportFlow&reportUnit=sample_report&output=pdf;
What I would prefer to have happen is for a download dialog box to be used and for the users to download the PDF to their computer, instead of it showing in the browser.
I've tried the following php code, but can't get it to work. I get a return value of false, but nothing in the server logs that shows an error.
ob_start();
header("Location: $src"); /* Redirect browser */
$report_contents = ob_get_contents();
ob_end_clean();
var_dump($report_contents);
I'm not really sure how to go about this...anyone got any ideas?
Thanks for the help.
You could buffer the file to the PHP server then output with force download:
header('Content-disposition: attachment; filename=huge_document.pdf');
header('Content-type: application/pdf');
readfile('https://mysite.com:8443/jasperserver/flow.html?_flowId=viewReportFlow&reportUnit=sample_report&output=pdf;');
See the notes about using readfile over an HTTP stream wrapper
http://php.net/manual/en/function.readfile.php
how about
$source=$url
header("Expires: 0");
header("Cache-Control: private");
header("Pragma: cache");
header("Content-length: $size");
header("Content-type: $type");
header("Content-Disposition: attachment; filename=$name");
readfile($source);
exit();

Save pdf to local server

I am creating a PDF file from raw binary data and it's working perfectly but because of the headers that I define in my PHP file it prompts the user either to "save" the file or "open with". Is there any way that I can save the file on local server somewhere here http://localhost/pdf?
Below are the headers I have defined in my page
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Transfer-Encoding: binary");
If you would like to save the file on the server rather than have the visitor download it, you won't need the headers. Headers are for telling the client what you are sending them, which is in this case nothing (although you are likely displaying a page linking to you newly created PDF or something).
So, instead just use a function such as file_put_contents to store the file locally, eventually letting your web server handle file transfer and HTTP headers.
// Let's say you have a function `generate_pdf()` which creates the PDF,
// and a variable $pdf_data where the file contents are stored upon creation
$pdf_data = generate_pdf();
// And a path where the file will be created
$path = '/path/to/your/www/root/public_html/newly_created_file.pdf';
// Then just save it like this
file_put_contents( $path, $pdf_data );
// Proceed in whatever way suitable, giving the user feedback if needed
// Eg. providing a download link to http://localhost/newly_created_file.pdf
You can use output control functions. Place ob_start() at beginning of your script. At the end use ob_get_contents() and save the content to a local file.
After that you can use ob_end_clean() or ob_end_flush() depending on whether you want to output PDF to browser as well, or you would redirect user to some other page. If you use ob_end_flush() make sure you set the headers before flushing the data.

Hide download file location. - Redirect download

I am selling a digital product and want to hide the true location of the download.
So I'm using a redirect script like this:
protected function redirectDownload ($realfilename) {
ob_start();
$mm_type="application/octet-stream";
header("Cache-Control: public, must-revalidate");
header("Pragma: no-cache");
header("Content-Type: " . $mm_type);
header("Content-Length: " .(string)(filesize($realfilename)) );
header('Content-Disposition: attachment; filename="'.$this->fakefilename.'"');
header("Content-Transfer-Encoding: binary\n");
ob_end_clean();
readfile($realfilename);
}
The zip file is always corrupted when I download it, but when I download it directly it is fine.
Does anyone know why this might be?
I think this was working fine on another server, but would need to confirm that.
If I can't solve this, is there any other techniques or services I can use to do this?
Open the downloaded(corrupted) file in an text-editor, i guess there has already been some output before you call the function.
You should better use ob_start() at the begin of your script instead of the begin of the function.

PHP Pass File Handle to user so that file downloads & saves to their machine

I am downloading a file from another server. I wish to push this file to my users rather than saving it to my server.
In other words, pass them the file handle so it just passes through my server and saves to their machine. How can I do this? I have this so far:
$handle = fopen($_GET['fileURL'], 'r');
$filename = stream_get_contents($handle);
How do I push this to the user, maybe using headers?
Thank you for any help and direction.
EDIT
I have the headers:
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
readfile("$filename");
Its just that it doesn't push the headers. I just get a blank page after about 15 seconds which looks like it downloading the file but not giving it to me.
I wish for the script to immediately send the headers to the user as a stream.
exit();
You can try this
$filetype = mime_content_type($filename);
header('Content-type: '.$filetype);
header('Content-Disposition: attachment; filename="'.$filename.'"');
UPDATE for your EDIT:
Do you have errors disabled, since this sounds like the headers already sent error?
error_reporting(E_ALL | E_STRICT);
You don't have to use fopen() when using readfile();
Just include the filename inside readfile() like this:
readfile($_GET['fileUrl']);
Although this is very dangerous security-wise as the user could specify any file on your file server. If you only have a few files you want someone to be able to download perhaps you should store them in an array (or database, preferebly)
Here's an array example:
$files = array('file1.jpg', 'file2.png', 'file3.pdf');
//assume $_GET['file_id'] == 0, 1 or 2
if (file_exists($files[$_GET['file_id']]))
readfile($files[$_GET['file_id']]);

Categories