I have link to XML file, which locate on the server. When user click button, he must take dialog to save XML file to local disk. I'm determine link to XML file in "a href", but browser opened this file, not save. If i "save link as.." all OK. Help me please to solve this problem.
Update:
Server - IIS.
XML files create dynamically.
onClick event i send to js link to my XML file, js POST link to php using ajax. How modify my php to open "Save Dialog" to save XML file ?
js:
function funk(url)
{
var ajax = getRequest();
ajax.onreadystatechange = function()
{
if(ajax.readyState == 4)
{
...
}
}
ajax.open("POST", "/do_query.php", true);
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var data = 'info='+url;
ajax.send(data);
}
php (do_query.php):
<?php
if (isset($_POST['info']))
{
$info = $_POST['info'];
}
?>
The XML file should be served with the HTTP header Content-Disposition: attachment. This tells the browser to download the file instead of opening it. Of course, the Content-Type header must also be set appropriately (application/xml is the generic XML mime type). How you add HTTP headers depends on your server configuration: please edit your question to add some details.
In Apache .htaccess, it's
Header set Content-Disposition attachment
In other servers, it'll vary.
Easiest way would be to make a php file that you link to, and have that php file contain something like
<?php
header('Content-Type: application/xml;');
header('Content-Disposition: attachment; filename=blah.xml;');
readfile('blah.xml');
that should force the file to be seen as a download.
Related
I've got a large form where the user is allowed to input many different fields, and when they're done I need to send the contents of the form to the server, process it, and then spit out a .txt file containing the results of the processing for them to download. Now, I'm all set except for the download part. Setting the headers on the response to the jQuery .post() doesn't seem to work. Is there any other way than doing some sort of iframe trick to make this work (a la JavaScript/jQuery to download file via POST with JSON data)?
Again, I'm sending data to the server, processing it, and then would like to just echo out the result with headers to prompt a download dialog. I don't want to write the result to disk, offer that for download, and then delete the file from the server.
Don't use AJAX. There is no cross-browser way to force the browser to show a save-as dialog in JavaScript for some arbitrary blob of data received from the server via AJAX. If you want the browser to interpret the results of a HTTP POST request (in this case, offering a download dialog) then don't issue the request via AJAX.
If you need to perform some kind of validation via AJAX, you'll have to do a two step process where your validation occurs via AJAX, and then the download is started by redirecting the browser to the URL where the .txt file can be found.
Found this thread while struggling with similar issue. Here's the workaround I ended up using:
$.post('genFile.php', {data : data}, function(url) {
$("body").append("<iframe src='download.php?url="+url+"' style='display: none;'></iframe>");
});
genFile.php creates the file in staging location using a randomly generated string for filename.
download.php reads the generated file, sets the MIME type and disposition (allowing to prompt using a predefined name instead of the random string in the actual filename), returns the file content and cleans up by deleting the source file.
[edit] might as well share the PHP code...
download.php:
<?php
$fname = "/tmp/".$_GET['url'];
header('Content-Type: text/xml');
header('Content-Disposition: attachment; filename="plan.xml"');
echo file_get_contents($fname);
unlink ($fname);
?>
genFile.php:
<?php
$length = 12;
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = substr( str_shuffle( $chars ), 0, $length ).'.xml';
$fh = fopen(('tmp/'.$str), 'w') or die("can't open file");
fwrite($fh,$_POST["data"]);
fclose($fh);
echo $str;
?>
Rather than using jQuery's .post(), you should just do a normal POST by submitting the form, and have the server respond with appropriate Content-Encoding and MIME-type headers. You can't trigger a download through post() because jQuery encapsulates the returned data.
One thing I see in use rather frequently, though, is this:
$.post('generateFile.php', function(data) {
// generateFile builds data and stores it in a
// temporary location on the server, and returns
// the URL to the requester.
// For example, http://mysite.com/getFile.php?id=12345
// Open a new window to the returned URL which
// should prompt a download, assuming the server
// is sending the correct headers:
window.open(data);
});
I want to write a php script to download some files(extensions - .apk, .dcm, .pdf, .zip etc...) on mobile browsers. I have written a php code to download those files and it is working fine on all the browsers(not mobile browsers). But I tried it using a HTC mobile and it is trying to open the file instead of downloading(like opening a web page).
How can I enable the download on mobile browsers?
Thank You
PS:
This is how I do it.
I use a jquery code to send some parameters to a php file and it will return the appropriate download file path.
jQuery code snippets is:
$.post('saveData.php',{ name: name.val(), email: email.val(), phone:phone.val(), address:address.val(), version:vers, swVersion:swvers, type:type },
function(data)
{
var links = data;
document.body.innerHTML += "<iframe src='" + links + "' style='display:hide;' ></iframe>";
});
"links" variable contains the download path return from the php file.
Iframe allow the download window to popup. But it does not work on the mobile browsers.
Try with the following headers:
header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename="filename"');
The idea is to set the content type to something that the browser doesn't know how to open - that way it will show the save dialogue. You can try it with the actual MIME type, it should work, but I can't test it right now.
I am using Yii Framework, TCPDF and jQuery to generate a pdf.
The pdf is generated by inputing in a form and submitting it using ajax.
The pdf is created but here is the problem when it returns to the client, it down not download.
here is the php code
$pdf->Output('Folder Label.pdf','D');
the jQuery on success function has
success: function(data) {
window.open(data);
}
Which i got from this site.
Can you please help
If the problem is that you are not getting the browser's download dialog for the PDF, then the solution is to do it this way:
First, redirect the browser (using window.location as the other answers say) to navigate to a special controller action in your application, e.g. with this url: http://your.application.com/download/pdf/filename.pdf.
Implement the action referenced in the URL like this:
public function actionPdf() {
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="filename.pdf";');
header('Content-Length: '.filesize('path/to/pdf'));
readfile('path/to/pdf');
Yii::app()->end();
}
This will cause the browser to download the file.
You need to save the PDF to somewhere on your server and then issue window.location = '/url/to/pdf-you-just-saved.pdf'; from your javascript. The users browser will then prompt them to download the PDF file.
in tcpdf , just pass this argument the Output method:
$pdf->Output('yourfilename.pdf', 'D');
that's all
Not quite, that will cause errors on some browsers, this is the correct way to set the window location.
window.location.assign( downloadUrlToPdf );
So
Send a request to make the pdf via Ajax to the server
Process and generate the pdf on the server
Return in the Ajax call the url to the file you just made
Use the above code fragment to open a download of said file
I am trying to get documents(ie. pdf, excel, word doc, etc) to open in a download box. for some reason the excel files work correctly but none of the others do. I think I need to setHeader using javascript(i believe that jquery does not have core functions that do this, but correct me if i'm wrong). here is a sample of my code.
$(function() {
$('a.media-link').click(function(event){
var fileName = $(this).html();
var property_id = $("input[name=capturePropId]").val();
//alert(fileName);
event.preventDefault(); //stop the browser from following
window.location.href = '../uploads/properties/'+
property_id+'/media/'+fileName+'';
response.setHeader("Content-Disposition", "attachment;
filename=\"" + fileName + "\"");
});
});
When i do this i get an error "response.setHeader response is undefinded. does anyone have any ideas?
You need to set the headers differently for each filetype. Take a look here.
You can't change server's response with JavaScript and you can't control how browser decides to open a new link outside of chosing this/new window. It is up to server to decide what to return for your request - i.e. it can response with the same JPG image for all requests or any other type of response.
You need to put the code that sets headers on the server that serves the request. You have correct code if your server is ASP.Net one ( http://support.microsoft.com/kb/260519).
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.