I am redirecting to an image with a Location header from PHP, and in firefox when you view the image and right click to save it prompts to save with the name of the PHP redirect script, not the name of the image. This behaviour is not present in the other browsers.
Here is the code of the file:
<?php
header("Location: foo.jpg");
Is there anyway to get firefox to use the correct name when a user opens the save dialog?
jewlhuq's suggestion to bypass php altogether works.
<?php print("<script>window.location='image.jpg';</script>"); ?>
Using php to read the file's contents and dump those to the browser with the proper headers including the following
header('Content-Disposition: inline; filename="desired-filename.jpg"');
also works.
Which is better depends on your application. I used the first for the problem listed above, in another application I needed to serve an image with a different file name than the one it is actually saved with, for that I needed the latter.
I have this download script running that allows people to click on a button and download a file without any new html pages opening. It all works well. Here is the script.
<?php
header('Content-disposition: attachment; filename=brochure-company-details.pdf');
header('Content-type: pdf');
readfile('brochure-company-details.pdf');
?>
However, I really want to be able to run the statcounter script at the same time, so as to document who is downloading the file. The Statcounter script works well enough when an html page opens and runs through its function. But I down't want a new page to open. I just want the download to start. The user experience will be that they only have the file download and without them knowing the statcounter will record the event.
Can you help?
What you want is not possible. (executing javascript on pdf download) Statcounter is an script and is executed by the browser by being included on the html. If you download a pdf file, you are not executing any js.
However, statcounter can see what links are pressed and therefore you can find which files were downloaded; as long your files are downloaded by using regular links on an html that has statcounter included. You don't need to do anything at all, they would be counted by default.
The idea Dachi gave, is to add an sql insertion to that php code of yours.
<?php
$dbh = new PDO("sqlite:/path/to/database.sdb");
//Put the insertion code here.
//Insert things like the IP, the login name, the time, etc.
header('Content-disposition: attachment; filename=brochure-company-details.pdf');
header('Content-type: pdf');
readfile('brochure-company-details.pdf');
That works too, and is a good choice if you are allowing downloads by not using regular links or not from an html that has statcounter.
I have a very basic question illustrated by the code snippet below.
This is the relevant part of a much bigger program in which I wish to download a zip file. The code as shown, with the comments in place, produce the expected browser output "Download the file now."
When I un-comment the code, the zip file is correctly downloaded to my browser!
However, the browser output is not produced. How do I regain control? I would like for the user to then have other options. (By the way, un-commenting the single "Content-disposition" line is sufficient to cause the loss of control.)
I have tried including the code, putting it in a function, many possible combinations of ob_start, ob_end flush, etc., all to no avail. I am sure I am overlooking something very fundamental and would appreciate some suggestions.
Thanks.
<?php
$sZipFN = 'file.zip';
// header("Content-type: application/zip");
// header("Content-disposition: attachment; filename=$sZipFN");
// readfile($sZipFN);
$sMsg = "Download the file now.";
?>
<html>
<body>
<p> <?php echo $sMsg; ?> </p>
</body>
</html>
You can't - you have to redirect to the options page and then start the download via javascript redirect (document.location = 'http://download.url/';)
This will start the download and leave the user on the options page like you desire.
Don't forget to include a 'Click here if the download fails to start' link somewhere near the top of the page (just in case javascript is disabled)
OK, I've had a good read through the "Related Questions" section and I haven't found this answer.
I'm using an ajax request to force a php download. Things are working fine on the PHP end. Let's say I've got a stream of data called DATA. Now, I want to pop up a "Save as..." dialog.
The browser has received a string of hex values. Now, what do I do with this DATA on the client (javascript) side?
This is the PHP code that I'm using, per the link above:
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename=$file');
readfile($file);
I've tried
window.open(DATA) -> hex stream doesn't exist (of course)
submitting a form with the action as DATA -> same problem
BTW, If I echo the file from PHP then use window.open, it works sometimes. But not for txt files or jpgs etc.
I've seen this working on other sites - how are they doing it? Thanks in advance.
Here's the answer I was looking for:
window.open("downloadPage.php");
...which pops up a box every time. The problem with the ajax request was that the returned file stream was interpreted as XMLHttpRequestObj.reponseText.
The browser apparently interprets this differently and doesn't allow the download.
I'm trying to accomplish a fairly simple task for my website, but I"m not sure exactly how to go about it. I want the user to be viewing a table, then click a button, at which point the user can save the contents of that table as a csv file. This request can sometimes be quite complicated so I generate a progress page to alert the user.
I have most things figured out except actually generating the csv file. (I use jQuery and PHP)
the jQuery code run on click:
hmis_query_csv_export: function(query_name) {
$.uiLock('<p>Query Loading.</p><img src="/images/loading.gif" />')
$.get({
url: '/php_scripts/utils/csv_export.php',
data: {query_name: query_name},
success: function(data) {
$.uiUnlock();
}
});}
the relevant PHP:
header("Content-type: text/x-csv");
header("Content-Disposition: attachment; filename=search_results.csv");
//
//Generate csv
//
echo $csvOutput
exit();
What this does is sends the text as the PHP file, but it's doesn't generate a download. What am I doing wrong?
If you are forcing a download, you can redirect the current page to the download link. Since the link will generate a download dialog, the current page (and its state) will be kept in place.
Basic approach:
$('a#query_name').click(function(){
$('#wait-animation').show();
document.location.href = '/php_scripts/utils/csv_export.php?query_name='+query_name;
$('#wait-animation').hide();
});
More complicated:
$('a#query_name').click(function(){
MyTimestamp = new Date().getTime(); // Meant to be global var
$('#wait-animation').show();
$.get('/php_scripts/utils/csv_export.php','timestamp='+MyTimestamp+'&query_name='query_name,function(){
document.location.href = '/php_scripts/utils/csv_export.php?timestamp='+MyTimestamp+'&query_name='+query_name;
$('#wait-animation').hide();
});
});
At PHP script:
#header("Last-Modified: " . #gmdate("D, d M Y H:i:s",$_GET['timestamp']) . " GMT");
#header("Content-type: text/x-csv");
// If the file is NOT requested via AJAX, force-download
if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
header("Content-Disposition: attachment; filename=search_results.csv");
}
//
//Generate csv
//
echo $csvOutput
exit();
The URL for both requests must be the same to trick the browser not to start a new download at document.location.href, but to save the copy at the cache. I'm not totally sure about it, but seems pretty promising.
EDIT I just tried this with a 10MB file and it seems that val() is too slow to insert the data. Hurrumph.
Okay, so I gave this one another go. This may or may not be completely insane! The idea is to make an AJAX request to create the data, then use the callback to insert the data into a hidden form on the current page which has an action of a third "download" page; after the insertion, the form is automatically submitted, the download page sends headers and echoes the POST, and et voila, download.
All the while, on the original page you've got an indication that the file is being prepared, and when it finishes the indicator is updated.
NOTE: this test code isn't tested extensively, and has no real security checks (or any at all) put in place. I tested it with a 1.5MB CSV file I had laying about and it was reasonably snappy.
Index.html
<a id="downloadlink" href="#">Click Me</a>
<div id="wait"></div>
<form id="hiddenform" method="POST" action="download.php">
<input type="hidden" id="filedata" name="data" value="">
</form>
test.js
$(document).ready(function(){
$("#downloadlink").click(function(){ // click the link to download
lock(); // start indicator
$.get("create.php",function(filedata){ // AJAX call returns with CSV file data
$("#filedata").val(filedata); // insert into the hidden form
unlock(); // update indicator
$("#hiddenform").submit(); // submit the form data to the download page
});
});
function lock(){
$("#wait").text("Creating File...");
}
function unlock(){
$("#wait").text("Done");
}
});
create.php
<?php
//create $data
print $data;
?>
download.php
<?php
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: text/x-csv");
header("Content-Disposition: attachment;filename=\"search_results.csv\"");
if($_POST['data']){
print $_POST['data'];
}
?>
The best way to accomplish this is to use a Data URI as follows:
Make the AJAX call to the server as per normal
Generate the CSV on the server-side
Return the data (either bare or inside a JSON structure)
Create a Data URI in Javascript using the returned data
Set window.location.href to the Data URI
See this link for instructions (paragraph #3, specifically): http://en.wikipedia.org/wiki/Data_URI_scheme
This way, you don't need to save any files on the server, and you also don't need to use iframes or hidden form elements or any such hacks.
I don't think you can make the browser download using a AJAX/JS request. Try using a hidden iframe that navigates to the page which generates the CSV
Well the point of using AJAX is to avoid a visible reload of the page. If you want a download, you want the opposite,- a brand new request from the browser. I'd say, just create a simple button pointing to your php page.
To echo and expand on what others have said, you can't really send the file using AJAX. One of the reasons for this is (and someone correct me if I'm wrong on this, please) that the page you're currently on already has sent its content headers; you can't send them again to the same window, even with an AJAX request (which is what your PHP file is attempting to do).
What I've done before in projects is to simply provide a link (with target="_blank" or javascript redirect) to a separate download PHP page. If you're using Apache, check out mod_xsendfile as well.