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.
Related
I'm generating a csv file for download using the following code.
/**#var array $results contains the results of an SQL query**/
$tmpFile = tmpfile(); //Create a temp file to write the csv to
fputcsv($tmpFile, array_keys($results[0])); //Write the column headers
foreach ($results as $result) { //write each row to the file
fputcsv($tmpFile, $result);
}
rewind($tmpFile); //Rewind the stream
$csv = stream_get_contents($tmpFile); //Get the file as text
fclose($tmpFile); //Done with the temp file.
//Set the download headers
header('Content-Description: File Transfer');
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="testDownload.csv"');
//Output the content
echo $csv;
exit(0);
The download appears to start normally, but after a second I get a message in firefox, "[The file] could not be saved, because the source file could not be read." I've tested this with chrome/safari and have gotten similar results. I've also tested with some static content (not from the database) without success.
In the developer console, I can inspect the network request and see that it comes back with status 200 and if I inspect the response, I see the complete file. I can even copy/paste it into a text file and open it in excel.
Additionally, if I comment out the header() lines, the file contents display in the browser without issue.
The content is only ~2500 rows, no special characters.
I want to create an application that when you import the CSV then it will export to .xlsx. But there are some conditins:
I need to change the column order and remove some of the columns when its exported
I need also to change the color and font(size,color)
And also create a multiple worksheets on single .xlsx file.
Which is better to use on this kind of application, can anybody help me and share some points which is better. I do the exploring on both but I need some guidance and some better solutions. Thank you.
// output headers so that the file is downloaded rather than displayed
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=file.csv');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// output the column headings
fputcsv($output, array('First Name', 'Last Name'));
You dot need to use a plugin or anything. PHP has the functionality within itself. What i wrote above is an example of defining the file and outputting the first row of the CSV.
Each use of fputcsv() outputs a new row.
So you can define the order of things by telling it in the array which value goes where in the row.
Of course after hours of pondering this problem, the first comment on my question lead me to solve it immediately.
The problem was that, although I was including this code within its own function at the top of the page, I was calling it only if a certain flag was set in the $_POST array. I wasn't checking for the flag until the end of the PHP file. I moved that check before the function, and it worked.
The original question is below:
I'm trying to use the fopen() function in PHP to output a CSV file, and although it contains the data I want, it also contains the entire HTML structure of the page, as well as inline stylesheets, before the content that I actually want to output.
I'm using this code (from here) pretty much unchanged. I'm very unfamiliar with PHP streaming and output, so I started from what I hope was a firm foundation:
$fileName = 'somefile.csv';
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Description: File Transfer');
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename={$fileName}");
header("Expires: 0");
header("Pragma: public");
$fh = #fopen( 'php://output', 'w' );
global $wpdb;
$query = "SELECT * FROM `{$wpdb->prefix}my_table`";
$results = $wpdb->get_results( $query, ARRAY_A );
$headerDisplayed = false;
foreach ( $results as $data ) {
// Add a header row if it hasn't been added yet
if ( !$headerDisplayed ) {
// Use the keys from $data as the titles
fputcsv($fh, array_keys($data));
$headerDisplayed = true;
}
// Put the data into the stream
fputcsv($fh, $data);
}
// Close the file
fclose($fh);
// Make sure nothing else is sent, our file is done
exit;
My assumption is that this example was intended to be included in its own external PHP file, but due to the constraints I'm dealing with, I'm trying to include it inline instead. I've mucked about with output buffering a bit with no positive results, but the PHP documentation on these is quite sparse, so there's probably something I'm missing.
Problem seems to be that, at the same time you try to output from the same PHP file, the CSV file AND some html content. You've got to separate them, to have 2 different URLs.
I guess your PHP code is surrounded by the html code (and css inline) you're talking about.
What you've got to do is:
have a PHP script that only outputs the CSV content (which only contains the code you showed us, with the opening php tag of course)
have another PHP script which produces html code, and provides a link to the previous script (for example).
You are on the right track with the 'include it inline' reason to why you're getting everything else before the data.
This script will need to be it's own separate file called directly, instead of including it inline in another script. I understand you have other database connections and such that have to be set up first. You'll have to extract those out of your standard pages and include those on this page.
Of course after hours of pondering this problem, the first comment on my question lead me to solve it immediately.
The problem was that, although I was including this code within its own function at the top of the page, I was calling it only if a certain flag was set in the $_POST array. I wasn't checking for the flag until the end of the PHP file. I moved that check before the function, and it worked.
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\"");
I'm no php expert (a mere beginner) but need some help!
After hours searching Google and trying out about 100 different scripts, I finally found one that does what I need - almost.
Basically, my site has a button marked 'Export to Excel'. Visitor to site clicks button and a download begins containing all data from a specified table.
I found this on here - PHP code to convert a MySQL query to CSV
which does exactly what I want except the user sees the following error when trying to open the file:
Error - 'The file you are trying to open, 'export.xls', is in a different format than specified by the file extension. Verify that the file is not corrupted and is from a trusted source before opening the file. Wo you want to open the file now?'
User clicks 'Yes' and file opens with all data! Brilliant! Except users will not open the file with this error.
I would be very grateful if someone knows a way to fix this.
Many thanks
TT
Or, you could just change the script in the above solution to return a file with the .csv extension. .csv files are associated with Excel, so they should open directly.
Ok, this results from a feature specified by Excel 2007 called Extension Hardening. You can turn it off, but that can only be done client-side. If you click "OK" or "Yes" the file should open anyway. Check this blog post for more info.
EDIT: What this means is that Excel is finding that the file is of a different type (say HTML or CSV) that what is specified by the file extension. Therefore Excel wants to warn you that this file is not what it says it is. Unless you are going to create native Excel files on the server then prompt the user to download them, there is no getting around this error except for each user to turn off Extension Hardening on their own computer.
if you make the first letters “ID” of a text file Excel incorrectly
assumes you are trying to open an SYLK file.
Meaning if the first row & column value is "ID", Excel will throw this warning. Just change it from "ID" to anything else.
Credit: http://alunr.com/excel-csv-import-returns-an-sylk-file-format-error/
Dim objXL As Excel.Application
Dim objWkb As Excel.Workbook
Set objXL = New Excel.Application
'turn off excel warnings
objXL.DisplayAlerts = False
'Open the Workbook
Set objWkb = objXL.Workbooks.Open(fpath)
functions sendFile($filename,$content_type="application/ms-excel") {
header('Content-type: '.$content_type);
header('Content-disposition: Attachment; filename=' . $filename);
readfile($filename);
}
I had the same problem so I looked at the following link: PHP code to convert a MySQL query to CSV
I modified one of the answers to get the headers to work.
include('DBFILE.PHP');
$select="SELECT * FROM SOMETable";
$result = mysqli_query($conn, $select);
if (!$result) die('Couldn\'t fetch records');
$num_fields = mysql_num_fields($result);
//This is what I changed...
$headers ="";
while ($property = mysqli_fetch_field($result)) {
$headers.= $property->name.",";
}
$headers.="\n";
//////
$fp = fopen('php://output', 'w');
if ($fp && $result) {
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="export.csv"');
header('Pragma: no-cache');
header('Expires: 0');
fputcsv($fp, $headers);
while ($row = $result->fetch_array(MYSQLI_NUM)) {
fputcsv($fp, array_values($row));
}
die;
}
I Tested this and it works like a charm, you just need to add your db connection or include the db.php file that you have.
you can change the name of the file if you edit the following line
header('Content-Disposition: attachment; filename="export.csv"');
Change export to what ever name you like.