refreshing after php serves a download [duplicate] - php

This question already has answers here:
PHP generate file for download then redirect
(11 answers)
Closed 3 years ago.
Page 1 links to page 2. Page 2 serves a download using the following code:
header("Content-disposition: attachment; filename= '$filename'");
header('Content-type: application/pdf');
readfile($file);
header("location: mainpage.php");
The result being the user "stays" on page 1 but is served a download.
How can I set things up, so that users remain on page 1 but it refreshes after the download is served.
I don't know javascript so I am hoping for a purely PHP solution.

In my opinion I wouldn't think you would necessarily need to refresh page1 at all. You should be able to force the download via a link within page1. See below:
Page1.php with a link
Download PDF
Page2.php
$filename = $_GET['pdf'] . '.pdf';
header('Content-type: application/pdf');
header("Content-disposition: attachment; filename= '$filename'");
header("location: $filename");
This will allow the download to start whilst you remain on page1.
Hope this is what you had in mind.

Didn't know of this before, but it's just one of the nice HTTP headers and most of us already know of it from HTML: Refresh.
Just add the following header call:
header('Refresh: 0; url=http://stackoverflow.com/');

You can check what the referer is by $_SERVER['HTTP_REFERER']. So you should be able to put this in you're page1.php:
if($_SERVER['HTTP_REFERER'] == page2.php) {
echo "<meta http-equiv=\"refresh\" content=\"0;url=http://www.yourdomain.com/page1.php\">";
exit();
}
This way, you check if your visitor is coming from page2.php, and if they are, you only parse a meta-tag which refresh the browser. When it is refreshed, it wouldn't refresh again, because the HTTP_REFERER is now page1.php.

No sure if you ever got this answered, but I had the same problem,
here is my solution
The AJAX jquery
$(function(){
$("#itemList").on("click", "a.downloadLink", function(){ //this binds a click event handler on the itemList container that will listen out for any a with class of downloadLink inside it being clicked
var link = $(this);
var item = link.parent();
var forId = item.data("itemid");
var started = new Date(); //the alternative to tracking time elapsed is to just use a simple counter you increment - "poll 5 times" etc. if your doing .5 second intervals, then 5 times = 2.5 seconds for example. Time elapsed may result in less polls, if a poll takes a long time to return, for example. Use whichever approach feels better.
var maxTime = 5000; //5 seconds
function poll(){
$.ajax({
type: "POST",
url: "Watergetstatus.php",
data: {FID: forId}, //this will be turned into a request for page1?forId=1&oldValue=2 - I expect it in this example to return a json-encoded response of {"changed":true|false, "newHtml":"replacementContent on success"}
datatype :'json',
success: function(data){
if (data.changed=true)
{
window.location.reload(true);
}
else {
var elapsed = (new Date())-started;
//window.location.reload(true);
if (elapsed <= maxTime) setTimeout(poll, 500); // Poll again in .5 seconds
//else you can assume the link didn't open / work / the database never changed etc - handle or ignore as needed
}
},
error: function() {
alert("borken"); //the request to the server bombed out; up to you if you want to simply re-queue for another try like above until the expiry time or if you want to show an error or just simply ignore it.
}
});
}
setTimeout(poll, 500); //wait 0.5 seconds before polling
});
});
The HTML had a large list of dynamic links
<div data-itemid="<?php echo $row_Files['FID']; ?> " >
<a class="downloadLink" href="PLC_FILES/WaterCheckOut.php?FID=<?php echo $row_Files['FID']; ?> " target=""><img src="PLCImages/download.fw.png"></a>
</div>
The Poling file watergetstatus.php
mysql_select_db($database_PLC, $PLC);
$query_files = "SELECT * FROM files WHERE FID = '{$_POST['FID']}'";
$files = mysql_query($query_files, $PLC) or die(mysql_error());
$row_files = mysql_fetch_assoc($files);
$totalRows_files = mysql_num_rows($files);
if($row_files['Status'] ==2)
{
$data= array("changed"=>true);
echo json_encode($data);
}
else
{
$data= array("changed"=>false);
echo json_encode($data);
}
THe download file link watercheckout.php
if ( $row_files['Status']==1 ) {
$file_path = $row_files['FileName'];;
$path_parts = pathinfo($file_path);
$file_name = $path_parts['basename'];
$file_ext = $path_parts['extension'];
$content_types = array(
"exe" => "application/octet-stream",
"zip" => "application/zip",
"mp3" => "audio/mpeg",
"mpg" => "video/mpeg",
"avi" => "video/x-msvideo",
);
$ctype = isset($content_types[$file_ext]) ? $content_types[$file_ext] : $ctype_default;
$file = $row_files['FileName'];
$path = "Historical/".date('Y-m-d-His');
$newfile = $path."_".$file;
$today = date('Y-m-d H:i:s');
header('Content-disposition: attachment; filename='.$file);
header("Content-Type: " . $ctype);
header('Content-Length: ' . filesize($file));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate');
header('Pragma: public');
mysql_select_db($database_PLC, $PLC);
mysql_query("UPDATE files SET Status = '2'");
ob_clean();
flush();
readfile($file);
rename($file, $newfile);
I have simplified my code and cut out alot, so it may be missing something, but this was the general frame work that I used and it works for me
Hope this helps someone, as there was not much out there

//----------------- TOP OF DOWNLOAD_PAGE.PHP ----------------------
$download_code = mysql_real_escape_string(urldecode($_GET['code']));
$download = mysql_real_escape_string(urldecode($_GET['download']));
$self = $_SERVER["PHP_SELF"]."?code=$download_code";
//refresh page after download...
echo"
<script type=\"text/javascript\">
function downloadRedirect(){
var redirect_url = \"$self\";
setTimeout(\"DoTheRedirect('\"+redirect_url+\"')\",
parseInt(0.5*1000));
}
function DoTheRedirect(url) { window.location=url; }
</script>
";
...
$filepath = "/var/www/vhosts/YOUR_DOMAIN.com/digital_downloads/";
if (isset($_GET['download'])) {
$file = $_GET['download'];
if (file_exists($filepath.$download) &&
is_readable($filepath.$download) && (preg_match('/\.zip$/',$download) || preg_match('/\.zipx$/',$download) )) {
...
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/octet-stream");
header("Content-Disposition: attachment; filename=\"".$download."\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filepath.$download));
ob_end_flush();
readfile($filepath.$download);
}//end if file_exists
}//end if isset
//----------------- BOTTOM HALF OF DOWNLOAD_PAGE.PHP ----------------------
//link generated to download and call JS to refresh page
echo "Click to Download

Related

download image from server folder using ajax call

I have website which uses ajax for most of cases. I have allowed user to upload image through ajax. When user clicks on a button the image is displayed in modal through an ajax call.
Now, I want to user to begin his download by clicking on image without closing the modal or refreshing. I did tried with href. It works fine but, as I mentioned, I want to keep user on same page with modal open.
The code I have tried untill now is:
$(document).ready(function(){
var imgname;
imgname = '';
$("#modalimage").click(function(){
imgname = $("#downloadimg").val();
downloadImage(imgname);
})
})
function downloadImage(imagename){
$.ajax({
type : "POST",
url : "download.php",
data : { imagename : imagename } ,
success : function(response){
alert('success');
}
})
}
download.php code is:
if ( isset($_POST['imagename']) ) {
$filename = $_POST['imagename'];
$filepath = 'images/'.$filename;
}
echo $filepath;
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($filepath));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
readfile($filepath);
The problem here is when ajax make call to download.php it create a response in form of some binary codes and small image codes without initiating the download. Is it possible to download the image by ajax call?
Instead of calling it by ajax place this link:
<a href="download.php?imagename=<?php echo urldecode($imagename); ?>">
Clich here to download
</a>
where $imagename is the file path. And the link content can be the text or a thumbnail or whatever you want.
And just change the download.php code to get the image through $_GET and not $_POST and, important, remove the echo that there is in there, there should be no other content than the headers and the file content:
if ( isset($_GET['imagename']) ) {
$filename = $_GET['imagename'];
$filepath = 'images/'.$filename;
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($filepath));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
readfile($filepath);
You will not be redirected to the file and the file will be downloaded. No need of ajax for this.
In case you really prefer using javascript you could create the link dinamically:
$(document).ready(function(){
$("#modalimage").click(function(){
var imgname = $("#downloadimg").val();
var link = document.createElement("a");
link.download = name;
link.href = 'download.php?imagename=' + encodeURI(imgname);
link.click();
});
})

Display message before creating excel in jquery and PHP

I am creating a web app in my company. The user can click on a button and an csv is created with MySQL data.
So far so god.
In jquery, when the user clicks the button it redirect to:
document.location.href = '/SDR/SDRJSON.php?type=' + id;
On PHP the csv file is created:
I connect to the database and create a the csv file:
while($row = $stmt->fetch(PDO::FETCH_NUM))
{
array_push($csv, $row);
}
$fp = fopen('file.csv', 'w');
foreach ($csv as $row) {
fputcsv($fp, $row, ';');
}
$FileName = 'PEW_'.$CountryCode;
fclose($fp);
header('Content-Encoding: UTF-8');
header('Content-type: text/csv; charset=UTF-8');
header("Content-Disposition: attachment; filename='".$FileName."'.csv");
header("Pragma: public");
header("Expires: 0");
echo "\xEF\xBB\xBF"; // UTF-8 BOM
readfile('file.csv');
On the page where the button is, the user clicks there and the page starts waiting for the server and then the csv file starts downloading.
For small files is ok, because it is instantaneous. But for larger files it takes like 10 / 15 seconds. Is it possible to show a message while the page waits for the server?
I don't Think PHP can echo while the csv is being made ... What you could do is split the "Document Formation" and "Document Download" into two parts.
Let Ajax Make a query for the CSV to be made . And when that has been completed the PHP (Document Formation) will echo the Path of the File.
Then After that You can use document.location.href to Newly Created File.
I ll give the code
ajax-code
$('#sample-button').click(function(){
$.ajax({
url : '/SDR/SDRJSON.php?type=' + id,
success : function(data){
if(data.url)
{
var urlToDownload = data.url;
alert("File is ready for download");
document.location.href = "http://www.domain.com/file/path/"+data.url;
// Make sure data.url has the full path or append the data.url
// with some strings to make sure the full path is reflected
// into document.location.href ...
}
else
{
alert("Something went wrong");
}
}
});
alert("CSV is being prepared Please wait... ");
});
documentFormation.php
while($row = $stmt->fetch(PDO::FETCH_NUM))
{
array_push($csv, $row);
}
$FileName = 'PEW_'.$CountryCode;
$fp = fopen($FileName, 'w');
foreach ($csv as $row) {
fputcsv($fp, $row, ';');
}
fclose($fp);
$response = array();
$response['url'] = $FileName;
echo json_encode($response); // You can handle rest of the cases where to display errors (if you have any)
// Your DocumentFormation PHP Ends here. No need for header() or readFile.
If you dont want the file to stay on server , Edit the document href to This PHP passing 'path' as the parameter
document.location.href = "documentDownload.php?path="+data.url;
documentDownload.php
$path = $_GET['path'];
$filename = end(explode("/" , $path));
header('Content-Encoding: UTF-8');
header('Content-type: text/csv; charset=UTF-8');
//Assuming $filename is like 'xyz.csv'
header("Content-Disposition: attachment; filename='".$filename);
header("Pragma: public");
header("Expires: 0");
echo "\xEF\xBB\xBF"; // UTF-8 BOM
// Reading file contents
readfile('Relative Path to File'.$path);
// Deleting after Read
unlink('Relative Path to File'.$path); // To Delete right after reading

dataurl to image for download in php

I'm creating image using canvas and using following script,
function getImage() {
var canvas1 = document.getElementById("images");
if (canvas1.getContext) {
var ctx = canvas1.getContext("2d");
var myImage = canvas1.toDataURL("image/jpg");
}
$('<form action="download.php" method="POST">' +
'<input type="hidden" name="aid" value="' + myImage + '">' +
'</form>').submit();
}
And in my Download.php file is,
<?php $img = $_POST['aid'];
echo "<img src=".$img.">";
?>
it showing image correctly. But i wanna give download button with jpg format or pdf format.
How i can use?
I used base64_decode(); method. But i cant solve.
Help me...
Thanks for all. but I got answer using,
file_put_contents();
But thing, i dont know how to use. Finally i got it from this Answer.
Answer is,
$data = 'data:image/png;base64,AAAFBfj42Pj4';
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
file_put_contents('/tmp/image.png', $data);
But still i'm waiting for download button with option of image/pdf format.
Try this:
PHP echo'ed image with link
<?php
$img = $_POST['aid'];
echo "";
?>
download_image.php
<?php
$img = "myimage.jpg";
// fix for IE catching or PHP bug issue
header("Pragma: public");
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// browser must download file from server instead of cache
// force download dialog
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
// use the Content-Disposition header to supply a recommended filename and
// force the browser to display the save dialog.
header("Content-Disposition: attachment; filename=".basename($img).";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($img));
readfile("$img");
exit();
?>

Force download file after query php mvc

I got stuck with the code left by the first programmer of the current webpage that I'm on. He create his own custom framework.
My problem is that I have created a function for file export cause there is a feature wherein I should export the query to textfile so client/user download it automatically via forcing the browser to download the generated file: heres the code of my force download.
Note: I have already search with others forums as well as at Stackoverflow but I can't find an answer. This is my current code:
if(!defined('APPLICATION_RUNNING')){
header("HTTP/1.0 404 Not Found");
die('acces denied');
}
if(defined('ANNOUNCE')){
echo "\n<!-- loaded: ".__FILE__." -->\n";
}
if(!class_exists('APP_Ajax')){
class APP_Ajax extends APP_Base_Ajax
{
function textfiles()
{
global $apptemplate, $appform, $appdb;
if(!$appform->form_valid($this->post['formid'])) // if not b\valid form
{
json_return_error(5);
}
else
{
if(!empty($this->post['form'])) //if the post of form is not empty
{
$e = array();
}
else
{
json_return_error(6);//alert if form is empty
}
if(empty($this->post['form']['rowid']))
{
json_return_error(252); // if rowid is empty then raise error
}
else
{
$rets = $this->post['form']['rowid'];
$ids = explode(',',$rets);
foreach ($ids as $kids)
{
$sql = pg_query("SELECT * from tbl_patient WHERE id='$kids'");
$info = pg_fetch_assoc($sql);
$text[] = ucwords($info['firstname']." ".$info['mi']." ".$info['lastname']).",".$info['medicalrecordnumber'].",".$info['referraldate'];
}
$output = implode( "\r\n" , $text );
$randfile = rand(12345689,999999999)."_".date('m-d-Y');
$f = fopen("templates/default/exports/".$randfile.".txt", "w");
fwrite($f, $output);
fclose($f);
$file_name = ABS_PATH.'templates/default/exports/'.$randfile.'.txt';
header('Pragma: public'); // required
header('Expires: 0');// no cache
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($file_name)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: text/plain');
header('Content-Disposition: attachment; filename="'.basename($file_name).'"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($file_name));
header('Connection: close');
readfile($file_name);// push it out
}
}
}
}
The code above produce no error, the file where created on the path I create but
the problem is that "No save as" or something, the browser do not download a file. When I use httpfox to view the headers, etc, etc, the result of the query is displayed on httpfox content tab, so nothings wrong with the code except that I want the browser to show the Download file(Save as dialog) so the user can save it to there Hard drives..
Note 2#: When I create a download link like Download, when I click the download link, the page returns me to the main page and no downloads at all.
Please give me a script or advice on how to work on this stuff. Thank you in advance.
Tell me if I'm missing something here.
Oops forgot to tell you, the website I'm on it do not allow external access to file for security that's why I can't link the export file it to other page for download. :)

Force Download via Ajax and PHP

i want to create a downloadscript which allows Force Download of JPGs.
This is my php script:
<?php
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Description: File Transfer");
header("Content-Type: image/jpg");
header('Content-Disposition: attachment; filename="'.basename($GET['a']).'"');
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize(($GET['a']));
readfile(($GET['a']);
?>
This is a code segment of my js code:
function downloadFile(a){
document.location = "download.php?a="+ a;
}
With this code sample nothing happens. If i append the result into a HTML-tag, it shows the content of the file.
Any ideas how to teach the browser to download this file?
EDIT: SCRIPT UPDATE
You can't download files with ajax. So, if you have something that should happen on ajax, you should return url in response and apply it like document.location = "url"to start download process.
One note here. As I remember, browser will block file download if it is initiated not by user click. So, this will work fine:
.click(function(){
document.location = "download url"
})
But if it is started not by user click, it will be blocked. So, code like this:
.click(function(){
$.ajax({...,
success:function(download_url_from_server){
document.location = download_url_from_server;
}});
})
will be blocked by browser. So, if you want to pass some data with a post, you may submit a form into hidden iframe or to blank page using <form target="...":
function checkToken(token){
var $form = $("#downloadForm");
if ($form.length == 0) {
$form = $("<form>").attr({ "target": "_blank", "id": "downloadForm", "method": "POST", "action": "script.php" }).hide();
$("body").append($form);
}
$form.find("input").remove();
var args = { a: "checkToken", b: token }
for (var field in args) {
$form.append($("<input>").attr({"value":args[field], "name":field}));
}
$form.submit();
}
And in script.php you need to execute code from download.php immediately, if token is Ok, or do a redirect to download script:
header("Location: download.php?a=" . $filename)
Setting the mime type to image/jpeg will most probably not work. So, you need application/octet-stream instead to force the download.
Replace the content type header in your php with the following:
header('Content-Type: application/octet-stream');
Also, One nice solution instead of using document.location is to inject an iframe. Use the following function in your success callback
function downloadFile(url)
{
var iframe;
iframe = document.getElementById("download-container");
if (iframe === null)
{
iframe = document.createElement('iframe');
iframe.id = "download-container";
iframe.style.visibility = 'hidden';
document.body.appendChild(iframe);
}
iframe.src = url;
}
It seems you have errors in your script.
First of all, correct speliing for GET variable is $_GET['a'], not $GET['a'].
The second issue here is that you have extra opening parenthesis, when I copied your code, I received 500 Internal Server Error response.
If we correct mistakes, it seems to work fine.
Just try corrected version of your code.
<?php
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Description: File Transfer");
header("Content-Type: image/jpg");
header('Content-Disposition: attachment; filename="'.basename($_GET['a']).'"');
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($_GET['a']));
readfile($_GET['a']);
?>
You're getting it confused a bit. As FAngel pointed out, you can't download files via AJAX. What you need to do is redirect the user to another page that then has your above PHP code in it. That PHP code should then allow the user to download the file directly. What you're attempting is absolutely possible, you just need to approach it from another direction, ie not with AJAX.
You can force download file with Mouse middle event:
const url = "https://www.google.com.vn/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png";
const forceDownload = url => {
try {
const link = document.createElement('a');
const fileName = url.substring(url.lastIndexOf('/') + 1, url.length);
const event = new MouseEvent( "click", { "button": 1, "which": 1 });
link.href = url;
link.download = fileName;
link.dispatchEvent(event);
} catch(e) {
document.location = url;
}
}
forceDownload(url);

Categories