PHP Force File Download [duplicate] - php

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!

Related

how to download a file with php and angular

I already uploaded a file and saved the path into my database, but the problem now is that I can't download it. I have already tested the PHP code and it works, but when I try to download it from the Angular side it doesn't. Instead I get this error in the console:
httpErrorResponse error: SyntaxError: Unexpected token p in JSON at position 0
at JSON.parse (<anonymous>)
at XMLHttpRequest.onLoad (localhost:4200/vendor.js:164415:51)
at ZoneDelegate.invokeTask (localhost:4200/polyfills.js:9799:31)
.........
ANGULAR SERVICE:
public getjointes(filepath:string){
const params = new HttpParams()
.set('filepath', filepath);
return this.http.get(url+'/download.php', {params: params });
}
TYPESCRIPT / function
telecharger(path:string) {
console.log(path);
this.stream.getjointes(path).subscribe(response => {
console.log(response);
});
}
PHP CODE:
$rest = $_GET['filepath'] ;
echo($rest);
$filepath = 'upload/' . $rest;
if (file_exists($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('upload/' . $rest));
readfile('upload/' . $rest);
header("Access-Control-Expose-Headers: Content-Disposition");
}
else{
echo ('noo');
}
Ok I'm going to assume the echo statements in your PHP are just for testing, based on the error messages you included in comments.
I think the problem you're having is that Angular assumes the response will be JSON and attempts to parse it. To avoid this behaviour, you can set the responseType parameter to "text" or "blob" (for binary data) in your code:
public getjointes(filepath:string) {
const params = new HttpParams()
.set('filepath', filepath);
return this.http.get(url+'/download.php', {params: params, responseType: "text"});
}
Note that any output before a call to header() will result in the HTTP header not getting set. Your PHP code calls header() after readfile(). That header will be ignored. In addition, if a file is not found you should say so with a proper 404 header. This way your client-side code can respond properly to failures. Your PHP should look like this:
$rest = $_GET['filepath'];
$filepath = 'upload/' . $rest;
if (file_exists($filepath) && is_readable($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('upload/' . $rest));
header("Access-Control-Expose-Headers: Content-Disposition");
readfile('upload/' . $rest);
} else {
header("HTTP/1.0 404 Not Found");
}

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();
});
})

Open PDF in new tab using PHP

I am simply trying to open a .pdf in another tab.
I start by using jQuery to post a couple of variables:
$('#resultsTable').on('click', 'tr > td > .view-pdf', function()
{
var $dataTable = $('#resultsTable').DataTable();
var tr = $(this).closest('tr');
var rowBookingNum = $dataTable.row(tr).data().JOB_REFERENCE;
var rowPartnerNum = $dataTable.row(tr).data().SHIPPER_CODE;
$.redirect('process/viewpdf.php', {'bookingnum':rowBookingNum, 'partnernum':rowPartnerNum });
});
The PHP script looks like this:
<?php
if(isset($_POST["bookingnum"]))
{
$bookingnum = $_POST["bookingnum"];
$partnernum = $_POST["partnernum"];
$dir = "D:/CargoDocsPDFs/" . $partnernum;
$file = $dir . "/" . $bookingnum . '.pdf';
if (file_exists($file))
{
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
}
?>
Using all of the above, I can get the .pdf to open in the same window. This causes the user to have to click the BACK button to go back to the previous screen.
I need the .pdf to open in a new tab. How can I adjust my code to make this happen?
You need to specify a target in $.redirect(url, [values, [method, [target, [traditional, [redirectTop]]]]])
See usage: http://github.com/mgalante/jquery.redirect
Desired usage:
$.redirect('process/viewpdf.php', {'bookingnum':rowBookingNum, 'partnernum':rowPartnerNum }, 'POST', '_blank');

Downloading PDF file with JQuery AJAX and 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

PHP multiple file download

I've seen this example on the documentation for PHP readfile
<?php
$file = 'monkey.gif';
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, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
How can you make it so It download multiple files say monkey.gif and girraffe.jpg
Preferably without ZIP files...
You can't. It's not a PHP limitation, it's an HTTP/Web-Browser limitation. HTTP doesn't provide a mechanism for sending multiple files over one request.
You could, however, have some PHP script that generates multiple iframes, which would initiate one download each, and fake it that way.
the whole method seems a bit pointless as a physical file actually exists on the server. just use JavaScript to open all the file urls, if you have set the header correctly in your .htaccess file then the files will just download.
I would do something like this
<script>
var files = ['filename1.jpg', 'filename2.jpg'];
for (var i = files.length - 1; i >= 0; i--) {
var a = document.createElement("a");
a.target = "_blank";
a.download = "download";
a.href = 'http://www.example.com/path_to/images/' + files[i];
a.click();
};
</script>

Categories