I have a script for exporting results of a mysql query as a csv file. The thing is that i use jquery to access the script. I need to know how i can return the data (already in csv format) with jquery. In other words, just to make myself clear because my english is a bit poor, when the user presses a button in the html file, a post request is sent to a php file which returns the data in csv format. I want to take that data with jquery and serve the .csv file to the user.
PHP file:
<?php
session_start();
header ("Content-type: application/csv\nContent-Disposition: \"inline; filename=my.csv\"");
include("config.php");
$query = $_SESSION['sqlQuery'];
$result = mysql_query($query) or die("Query failed : " . mysql_error());
echo "ID,STATUS,CATEGORY,TITLE,DATE,URL\r\n"; //header
while($row = mysql_fetch_row($result)) {
echo "$row[0],$row[4],$row[3],$row[1],$row[2]\r\n"; //data
}
?>
I need something in the HTML like:
$("#exportToCsv").click(function(){
$.post("export.php",function(data){
here the code for exporting much like downloading a file
});
});
You can just link to the file (no ajax, no $.post) with the header henchman said. It will download the file. Ajax is ment for javascript to get the file, not to perfom download.
for which part of this task do you need help?
The following command prints a file to the user:
http://php.net/manual/en/function.file-get-contents.php
eg:
echo file_get_contents("myfile.csv");
edit
Try to add the following headers to your php-page, which will be called for your ajax call:
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=\"export.csv\"");
Related
I have this code to create a csv in php and after make possible the download:
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=data.csv');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// output the column headings
fputcsv($output, array( //values...));
$rows = #mysql_query("SELECT //values from table");
// loop over the rows, outputting them
while ($row = mysql_fetch_assoc($rows)) fputcsv($output, $row );
But, after the download, when I open the file, what I see is the content of the page with the tags, in addition to the csv content.
How is possible to see all the content of the csv without the tags page?
thanks in advances
If I understand correctly - I think the issue is that you are calling a function with the code you have posted when you have already outputted HTML (either intentionally or otherwise), when what you should do is link to a separate PHP Script containing your code, or not output before your code sample in called.
When you declare those headers in your code, you are telling the browser that the content is .csv but you are outputting this in the middle of HTML output (where likely HTML headers have already been sent due to some prior output).
Instead you can put your code in a separate PHP script and then create a link to it from other outputted HTML pages. This will mean that when your code is loaded the csv headers will be sent with the correct content only.
I have a button. By clicking the button, I want to export some data shown on the webpage to a file for downloading.
I am doing this in this way: I have a export.php. I send the data as the parameter to PHP file (another parameter is filename), and PHP server create a file and write the data, and then send file. Code is like:
$filename = $_GET['filename'] . '.csv';
$export = $_GET['export'];
$writer = fopen($filename, 'w') or die('cannot create');
fwrite($writer, $export . "\n");
fclose($writer);
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename='.basename($filename));
readfile($filename);
unlink($filename);
exit();
For cases that the data are short, it works fine. But if the data are long, since the data are passed as part of the URL, I will get "Request-URI Too Large" error.
Is there any alternative way to do that? Is it possible to directly write data using JavaScript?
It sounds like you are sending to export.php with a GET, when you should be using a POST. GET is limited to 2048 characters, while a POST is not limited.
You'll need to POST the data to the server. Change the METHOD in your FORM tag to POST (in your html not your php code).
Each browser limits the size of the query string / length of the URL and the limit is browser dependent. You can POST a very large amount of data to the server however. The only limit is how fast is the user's upstream bandwidth and their patience.
Instead of passing the data as a query string, use javascript to create an iframe and build a form which then posts to the php file.
IF your using jquery there's a good tutorial http://tutorialzine.com/2011/05/generating-files-javascript-php/
i have made some inputs in my database table and it is saved together with its html tags.
now, i want it to be downloaded by a user.
i want to remove the html tags.
Since the file input at my database table has no format, i want the download file to be downloaded as a document file and must be compatible in MS word.
so far i have this for the download page
<?php
if(isset($_GET['id']))
{
include 'connect.php';
$id = $_GET['id'];
$result = mysql_query("SELECT title, content, format FROM activity WHERE id = '$id'");
list($title, $content, $format) = mysql_fetch_array($result);
strip_tags($content);
header("Content-type: $format");
header("Content-Disposition: attachment; filename=$title");
echo $content;
mysql_close;
exit;
}
?>
There are more than one only problem on your script:
First of all, if you're sure there's only 1 value return by your query, add LIMIT 1.
Then, to return your value, use
$contents = $result[0]['content'];
Moreover, filename is the filename, not the content.
Finally, read some docs about HTTP headers: Content-Disposition is not sufficient to send your file, even you're wanted to be compatible with MSword...
"the download prompt will appear. and the i download the file. and i open it in MS WOrd, it shows the content i saved with the html tags"
=> maybe you just htmlentities your tag in the database.
Try this:
<?php
strip_tags(html_entity_decode($contents));
?>
I have a php script that gets called via an ajax call. Values are sent to this script to build a pdf. I want to send the pdf to the browser, but since the script that builds the pdf returns to the page with the javascript I can't see how to do this. Any ideas?
I would recommend something a bit different. Instead of AJAX call make a redirect to an URL like this:
./path_to_pdf_script/script.php?param1=val1¶m2=val2
This script would be the one which generated the pdf. Place somewhere on top of the script this header:
header('Content-type: application/pdf');
And simply echo the string the pdf content is in. If you want the user to download this pdf instead of viewing you could do the AJAX call with the example found HERE:
from php.net
If you want the user to be prompted to save the data you are sending,
such as a generated PDF file, you can use the ยป Content-Disposition
header to supply a recommended filename and force the browser to
display the save dialog.
<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');
// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');
// The PDF source is in original.pdf
readfile('original.pdf');
?>
You could use an iframe instead of an ajax request and force-download the pdf file.
As you noticed, your AJAX call can't directly output the PDF to the browser. One workaround is to remove AJAX and send the user directly to the page that generates the PDF. This approach is very common and well documented. But there is a way to use AJAX to generate the PDF, so that the user will stay on the web page until the file is ready.
Your AJAX call could answer with a JSON object with 2 exclusive fields:
"pdfurl" if the pdf file was successfully created and written to the disk,
"errormsg" if there was an error.
Something like (in PHP):
<?php
//...
if (writepdf($filename, ...)) {
$result = array('pdfurl' => '/files/' . $filename);
} else {
$result = array('errormsg' => 'Error!');
}
echo json_encode($result);
Then the page's javascript could contain (jQuery example):
$.ajax({
type: "GET",
url: "ajaxcreatepdf.php",
data: {userid: 1},
dataType: "json",
success: function(data, textStatus) {
if (data.pdfurl) {
window.location.href = data.pdfurl;
}
else {
$("#messagebox").html(data.errormsg);
}
}
});
The Ajax request is not direct visible to the user, so a redirect make no sense
You need to load this PDF into an existing or new browser window after the ajax has returned.
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.