How can I display a Thankyou page after user downloads file? - php

I am using this little pusher php file to download an 'exe' file for the user to save when they fill-out a form.
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
with this method there is no link to the online $file location for someone to follow but for some reason I cannot display a thank you page after or even immediately before the code is executed.
I've tried header( "Location: $thankyouurl" ); immediately after the above code, but nothing is ever displayed and I've tried echoing the html source of the thank you page just prior to running the above code, but that causes the exe file to be downloaded to the web page actually crashing the browser.
Any suggestions???

Point the user directly to a static page that displays your thank you message. Then, use JavaScript to set the window.location to your download script.
If your download page's headers are set up correctly, the browser will start downloading the file, while your user is reading your thank you message.
Make sure to display a direct download link in case the user has JavaScript disabled.
Example:
index.php
Click here to download.
thankyou.php
<html>
<head>
<script type="text/javascript">
function startDownload() {
window.location = "/download.php";
}
</script>
</head>
<body onload="startDownload();">
<h1>Thank you!</h1>
<p>Your download will start in a moment. If it doesn't, use this direct link.</p>
</body>
download.php
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
Update
In order to pass data from index.php on to the download script, you could use GET variables. The link to the thankyou.php page would become thankyou.php?download=12 where download is an ID for you to grab the correct file. You would then pass that variable on to your download script by echoing it out in your markup like so:
index.php
Click here to download.
thankyou.php
<html>
<head>
<script type="text/javascript">
function startDownload() {
window.location = "/download.php?file=<?=$_GET['download']?>";
}
</script>
</head>
<body onload="startDownload();">
<h1>Thank you!</h1>
<p>Your download will start in a moment. If it doesn't, use this direct link.</p>
</body>
You'd then grab the value in your download script and handle it any way you like.

Not too sure on this, would a...
header('Location: thanks_page.php');
...not work,. if placed after the readfile()? Unsure on it really, only my thoughts!

You can open the "download page" with an "windows.open( 'url to download file' )"
Example:
<script type="text/javascript">
function openDownload()
{
window.open( "http://domain.com/download.php?file=file.pdf" );
window.location = "http://domain.com/thanks.php";
}
</script>
Opening a window that directly download a file, this will be automatically closed when you chose save or cancel and then, the "parent" window redirect to thanks page.

Using your original method, add header('location: thank-you-page.php'); to the end, along with an exit, as shown here:
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
header('location: thank-you-page.php');
exit;

Related

Unable to download file in php

I have a file download code using php and my code at download page is follows.
if (file_exists($strDownload)) {
//get the file content
$strFile = file_get_contents($strDownload);
//set the headers to force a download
header("Content-type: application/force-download");
header("Content-Disposition: attachment; filename=\"" . str_replace(" ", "_", $arrCheck['file_name']) . "\"");
//echo the file to the user
echo $strFile;
//update the DB to say this file has been downloaded
mysql_query("xxxxxxxx");
exit;
}
Where the function file_exists() passed with valid check and my $strDownload variable will be something like /home/public_html/uploads/myfile.zip which is located in server folder. But when I trying to download the file instead of downloading, the page displays the full encrypted source of the file. How can I make it downloadable?
EDIT: for the information, myself trying to use this bit of code inside the wordpress system and my file path will be something like http://example.com/wp-content/uploads/2016/02/myfile.zip. Also in the above mentioned code myself checking the file_exists() condition for the server path which is already mentioned above and it returns 1 as desired.
Try this
if (file_exists($file))
{
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
It is solved by using the above bit of codes at beginning of php page. Ie, before declaring the famous wordpress tag get_header();
If we use the above code after get_header(); tag of wordpress, it results in the opening of page first and hence it writes the source of the file in the page instead of downloading since the meta tags are already set.

How to trigger a download prompt through post callback function

simple question I guess, but can't figure it out... Here's the problem:
In the front end, I export some user-selected data to the server to dynamically create a file:
$("#export-button").click(function() {
$.post("'.$postUrl.'",{variable:exportSelection},
function(data) {
console.log(data);
}
);});
Then, after I receive the data and create/save the file on the server, I am doing the following in php:
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;}
What am I supposed to do in the post callback function instead of printing on the console in order to get a download prompt?
UPDATE: OK - I just realised that my #export-button was an anchor tag with no href... Now when I point to the file on the server, the problem is that when I click, it follows the link prompts to save file etc., but it gets to the file BEFORE the "new" version is generated (so using the previous selection at each click)
OK - I figured it out. I just needed to disable the link from pointing anywhere and then do:
window.location = 'my_file_location.doc';
... inside the callback function

Render view after image file is downloaded in Yii

public function actionViewDownload(){
// some in internal processing php commands (no echo)
exec($command); // command to be executed compulsary
$file = "/images/sample.jpg"; // some images file
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
}
$this->render('view',array('data'=>$data)); // render the other view of the controller after/during download.
}
I need to execute a command, then download the image file and after or during downloading render, the view.
If I render the view before downloading it prompts "Header cannot be modified. Headers already sent"
and if I render the view after the download then view is now shown on browser but the file gets downloaded.
My question here is that how can I achieve three tasks : execution of the command (this must be first), render and download.
By the looks of it you are trying to do something like sourceforge does when you ask to download a project where the deliverable is pushed to the user as the page is rendered.
I am assuming that the exec generates the image.
You really need to split this into 2 actions:
public function actionViewDownload(){
// some in internal processing php commands (no echo)
exec($command); // command to be executed compulsory
$file = "/images/sample.jpg"; // some images file
$this->render('view',array(
'data'=>$data,
'img'=>$file)
);
}
Then the view contains something like:
<img src="<?php echo controller/getdeliverible?file=$img; ?>"/>
which in turn calls:
public function actionGetDeliverible($file){
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
}
}
My above code is rough (you'll have to fill it in properly) but you get the idea. Basically as the view is rendered the image will pop up and ask you to save it. It will appear to the user that both things are happening together.
The nice thing about doing it this way is that you can do something after you have read the image to the user like delete it if it was a temporary file so it can't be downloaded again.

How to stream PDFs from outside the web root to google's docs reader

Im trying to workout if i can stream PDF files from behind the web root via an image/pdf viewer. Google's documentation says to embed a PDF in an HTML page you just use html and include an embed and point to the file.
http://docs.google.com/viewer?url=YourDocumentUrlHere
However for the purposes of security I am using a document/image script that streams the file to the browser and therefore the filepath remains hidden from the view of the user and unable to be accessed by google documents.
The output sent by the document image script is in the form
header('Content-type: application/pdf');
readfile("/home/******/*****/images/enquiries/23251/23251-1.pdf");
can anyone help me with this?
JUST IN CASE ANYONE WAS WONDERING... i added this to the image server script (imageserve.php)
if ($type = "application/pdf") {
header('Content-Description: File Transfer');
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
} else
and then on the page where i wanted to display the pdf i added
$temp = "home/..../..../development/imageserve.php?filename=xxxxxx";
<embed style="width:1200px; height:730px;" name="plugin" src="$temp" type="application/pdf">

PHP download/redirect

Okay so this is how I rewrote it. Any changes? Will this work? I've added the Javascript at the end with the timeout.
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
}
?>
<script type="text/Javascript">
window.setInterval(function()
{
window.location = "www.moneymovers.com";
}, 5000);
</script>:
You can't download and then do a header redirect. The client is going to redirect as soon as it sees the header, which means the download won't work. But you also can't output the header after the download, because then the redirect won't happen. Either way, it's not gonna work.
I would recommend doing this at a different level. For example, when the user clicks the download link, have some JavaScript start the download in a new tab/window and then redirect to the desired location in the current tab.
You can put the location header wherever you want, as long as nothing has been outputted (echo).
If you have outputted something, you can output something like this to redirect :
<script type="text/javascript">
window.location = "www.example.com";
</script>
EDIT :
In your case, it is not possible to do what you're looking for, as far as I know. You will have to manage this case in the caller page. The Javascript will not be called because you've modified the Content-Disposition.

Categories