Downloading PDF file with JQuery AJAX and PHP - php

I already found many questions here in SO about the theme, but any of them helps me with a specific problem.
I need to send a ajax request to PHP and then download a PDF file.
This is my Javascript
$('body').on("click",'.download-file', function(e) {
e.stopPropagation();
var id = $(this).attr('data-id');
$.ajax({
url: 'app/myPage/download',// The framework will redirect it to index.php and then to myPage.class and method dowload
data: id,
type: 'POST',
success: function (return) {
console.log(return);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("Error... " + textStatus + " " + errorThrown);
}
});
});
Here is my PHP file:
class myPage{
public function download()
{
$id = $_POST['id'];
$filePath = $this->methodToGetFile($id);
$name = end(explode('/',$filePath));
$fp = fopen($filePath, 'rb');
header("Cache-Control: ");
header("Pragma: ");
header("Content-Type: application/octet-stream");
header("Content-Length: " . filesize($filePath));
header("Content-Disposition: attachment; filename='".$name."';");
header("Content-Transfer-Encoding: binary\n");
fpassthru($fp);
exit;
}
}
With this approach, I have the PDF "printed" in the console like
%PDF-1.5%����1 0 obj<</Type/Catalog/Pages 2 0 R/Lang(pt-BR) /StructTreeRoot 8 0 R/MarkInfo<</Marked true>>>> ....
So, I'd like to know what should I do to open this file and download it.
In the linked questions I see something about window.location, but I don't know how can I use it.
I've already tried change the PHP headers to try force the download, but no success with it. In these cases I just receive null in the javascript nothing happens. Here are the modified headers:
header('Content-Type: application/pdf');//tried with this option
//header('Content-Type: application/octet-stream');// also tried with this other option
header('Content-Disposition: attachment; filename=' . $name);
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($filePath));
Are there some good approach to do this?

i don't think this approach to downloading a pdf will work. Javascript is sending the request, and php is sending the response. You want the response to go directly to the browser, not to javascript. You should change the download link to go directly to the download location. No ajax / javascript needed. Like this:
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();
});
})

Download file via PHP

I'm trying to download a zip file without revealing the URL to the user. The file should only be accessible by authorized users.
Currently I'm doing this:
// check authentication and request method etc...
// ...
$file = '../../filename.zip';
$filesize = filesize($file);
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: private');
header('Content-Length: ' . $filesize);
ob_clean();
flush();
echo readfile($file);
die();
And I can see the file is downloaded somehow in the Chrome network tab (it shows in the Response tab) and ~3MB are transferred (which is the filesize), but the file isn't downloaded in the browser.
I'm doing a simple GET request, btw.
Thanks for your help,
Tobias
EDIT: Okay, apparently I also had an error on the client side and now the file is being downloaded in the browser, but it's only a 1KB zip containing Response with status: 200 OK for URL: xxx.
My request looks like this:
let headers = new Headers({'Accept': 'application/zip'});
let options = new RequestOptions({ headers: headers, responseType: ResponseContentType.Blob });
this.authHttp.post(environment.apiUrl + 'rewards/download/', data, options)
.map(res => new Blob([res],{ type: 'application/zip' }))
.catch((error:any) => Observable.throw(error.json().error || 'Server error'))
.subscribe(
data => {
//console.log(data);
window.location.href = window.URL.createObjectURL(data);
},
error => {
console.log("Error downloading file.");
},
() => console.log("Download completed."));
EDIT2: Okay, got it. Apparently I had to use .map(res => new Blob([res.json()],{ type: 'application/zip' })) in the request. Also now I'm using FileSaver.js instead of window.location, but I don't think that affected the problem.
i think you just need to redirect ur method to your physique zip file.
i mean you need just to add :
header("Location: $url_physique_of_ur_zip_file");
before
ob_clean();
flush();
and replace $url_physique_of_ur_zip_file by your physique url of your file
i wish u understand me because this solution work for me
Okay, got it. Apparently I had to use .map(res => new Blob([res.json()],{ type: 'application/zip' })) in the request. Also now I'm using FileSaver.js instead of window.location, but I don't think that affected the problem.

Downloading CSV file with PHP

I am trying to download a CSV file with PHP but I can not make it to get the dialog box.
I have changed the headers and used the readfile() function as shown here
This is my code:
$nodeId = 'something';
$filename = "/var/www/dkar/ruralBroadband/ruralApp/rural/csvExports/$nodeId.csv";
header('Content-type: text/csv');
header('Content-disposition: attachment; filename ="report.csv"');
readfile($filename);
** EDIT **
Tried also with this as suggested:
header('Content-Disposition: attachment; filename="report.csv"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize('report.csv'));
When I am checking the response in Firebug I can see the whole CSV file returned. Also the headers change into:
Content-Type text/csv
Content-disposition attachment; filename ="report.csv"
So I can not figure out why I dont get the dialog box to save the file.
Add these headers:
header('Content-Disposition: inline; filename="report.csv"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($filename));
After all I didn't use the above method and I did that, which works fine and its more straight forward:
var ajaxurl = 'exportNodeData.php', // script to run
data = {nodeId:nodeId}; // data to pass
$.post(ajaxurl, data, function (response) {
document.location.href = 'https://www.ruralauditor.gr/csvExports/'+nodeId+'.zip';
});
This is the ajax request, which I execute in order to create the CSV file (which is also zipped). I then use this line:
document.location.href = 'https://www.ruralauditor.gr/csvExports/'+nodeId+'.zip';
in order to force the download of the file.

Copy image file from server to disk in PHP

I have a js script that saves an image as .jpg in a specific folder on the server:
$data = substr($_POST['imageData'], strpos($_POST['imageData'], ",") + 1);
$decodedData = base64_decode($data);
$fp = fopen("imgdownload/cc.jpg", 'wb');
fwrite($fp, $decodedData);
fclose($fp);
The next step would be for the user to save it on his/her disk, the best would be to open a dialog box "save as" and choose the name and location, but just forcing download to a set location would be a dream.
I've tried:
$file = 'imgdownload/cc.jpg';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: image/jpg');
header('Content-Disposition: attachment; filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
And other things without success. What am I doing wrong and how to do it right?
EDIT - this is my JS:
savePicture: function() {
$(this.el).find('canvas').attr('id', 'myCanvas');
var data = document.getElementById("myCanvas").toDataURL();
$.post("api/process.php", {
imageData: data
}, function(data) {
//window.location = data;
});
},
You cannot trigger a download in response to a background AJAX request. You'll have to direct the main browser to the URL where the download occurs. E.g., in your AJAX callback:
window.location = '/download.php';
That means you'll need to store the file server-side in the AJAX upload request to then have it available for download in the separate following request to download.php somewhere.

PHP Force File Download [duplicate]

This question already has answers here:
Forcing to download a file using PHP
(10 answers)
Closed 9 years ago.
I am trying to use PHP to force a download on a client computer (with the file dialog- nothing sinister). I have found many pages that recommend I use the header() function to control the response from my PHP script, but I am having no luck with this. The code I have is as follows:
$file = $_POST['fname'];
if(!($baseDir . '\\AgcommandPortal\\agcommand\\php\\utils\\ISOxml\\' . $file)) {
die('File not found.');
} else {
header('Pragma: public');
header('Content-disposition: attachment; filename="tasks.zip"');
header('Content-type: application/force-download');
header('Content-Length: ' . filesize($file));
header('Content-Description: File Transfer');
header('Content-Transfer-Encoding: binary');
header('Connection: close');
ob_end_clean();
readfile($baseDir . '\\AgcommandPortal\\agcommand\\php\\utils\\ISOxml\\' . $file);
}
I am calling it using this JavaScript:
$.ajax({
url: url,
success: function(text) {
var req = new XMLHttpRequest();
req.open("POST", 'php/utils/getXMLfile.php', true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.send('fname=' + encodeURIComponent(text));
}
});
This returns the contents of the file as text, but does not trigger a download dialog. Does anyone have any suggestions?
Instead of using AJAX, just redirect the browser to the relevant URL. When it receives the content-disposition:attachment header, it will download the file.
Few suggestions:
1.
if(!($baseDir . '\\AgcommandPortal\\agcommand\\php\\utils\\ISOxml\\' . $file)) {
Instead:
if(!file_exists($baseDir ....)){
2.Don't need size.
3.Try this one:
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($fullpath));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
ob_clean();
flush();
readfile($fullpath);
exit;
I would try sending a header from PHP like this, to replace your application/force-download header:
header("Content-type: application/octet-stream");
Kolink's answer worked for me (change the window location to the php file), but as I want to send POST variables along with the request, I ended up using a hidden form instead. The code I am using is as follows:
var url = 'php/utils/getXMLfile.php';
var form = $('<form action="' + url + '" method="post" style="display: none;">' +
'<input type="text" name="fname" value="' + text + '" />' +
'</form>');
$('body').append(form);
$(form).submit();
Thanks for all the answers!

Categories