У меня есть данные в базе данных MySQL. Я отправляю пользователю URL-адрес, чтобы получить его данные в виде файла CSV.
У меня есть электронная почта со ссылкой, запросом MySQL и т. д.
Как я могу, когда они щелкают ссылку, получать всплывающее окно для загрузки CVS с записью из MySQL?
У меня уже есть вся информация, чтобы получить запись. Я просто не понимаю, как заставить PHP создать файл CSV и позволить им загрузить файл с расширением .csv.






Чтобы он отправил его как CSV и дал имя файла, используйте header ():
header('Content-type: text/csv');
header('Content-disposition: attachment; filename = "myfile.csv"');
Что касается создания самого CSV, вы просто перебираете набор результатов, форматируете вывод и отправляете его, как и любой другой контент.
Пытаться:
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=file.csv");
header("Pragma: no-cache");
header("Expires: 0");
echo "record1,record2,record3\n";
die;
так далее
Обновлено: вот фрагмент кода, который я использую для необязательного кодирования полей CSV:
function maybeEncodeCSVField($string) {
if (strpos($string, ',') !== false || strpos($string, '"') !== false || strpos($string, "\n") !== false) {
$string = '"' . str_replace('"', '""', $string) . '"';
}
return $string;
}
В общем, следуйте RFC 4180 при создании файлов CSV. tools.ietf.org/html/rfc4180
Чтобы уточнить, правильный заголовок HTTP Content-Type для CSV - это text / csv, а не application / csv. Я сомневаюсь, что любой современный браузер будет заботиться об этом в любом случае, но, поскольку существуют стандарты, мы могли бы их использовать.
@Oleg Barshay: Боже мой, этот RFC - шедевр: «Если для заключения полей используются двойные кавычки, то двойные кавычки внутри поля должны быть экранированы, поставив перед ними другую двойную кавычку». ЕЩЕ ОДНА ДВОЙНАЯ ЦИТАТА!
Создайте свой файл, затем верните ссылку на него с правильным заголовком, чтобы запустить «Сохранить как» - при необходимости отредактируйте следующее. Поместите свои данные CSV в $ csvdata.
$fname = 'myCSV.csv';
$fp = fopen($fname,'wb');
fwrite($fp,$csvdata);
fclose($fp);
header('Content-type: application/csv');
header("Content-Disposition: inline; filename = ".$fname);
readfile($fname);
Использование «встроенного» Content-Disposition означает, что браузер должен попытаться отобразить его без загрузки (IE обычно встраивает для этого экземпляр Excel). «вложение» - это то, что необходимо для принудительной загрузки.
<?
// Connect to database
$result = mysql_query("select id
from tablename
where shid=3");
list($DBshid) = mysql_fetch_row($result);
/***********************************
Write date to CSV file
***********************************/
$_file = 'show.csv';
$_fp = @fopen( $_file, 'wb' );
$result = mysql_query("select name,compname,job_title,email_add,phone,url from UserTables where id=3");
while (list( $Username, $Useremail_add, $Userphone, $Userurl) = mysql_fetch_row($result))
{
$_csv_data = $Username.','.$Useremail_add.','.$Userphone.','.$Userurl . "\n";
@fwrite( $_fp, $_csv_data);
}
@fclose( $_fp );
?>
Сначала сделайте данные в виде строки с запятой в качестве разделителя (разделенных знаком ","). Что-то вроде этого
$CSV_string = "No,Date,Email,Sender Name,Sender Email \n"; //making string, So "\n" is used for newLine
$rand = rand(1,50); //Make a random int number between 1 to 50.
$file = "export/export".$rand.".csv"; //For avoiding cache in the client and on the server
//side it is recommended that the file name be different.
file_put_contents($file,$CSV_string);
/* Or try this code if $CSV_string is an array
fh =fopen($file, 'w');
fputcsv($fh , $CSV_string , "," , "\n" ); // "," is delimiter // "\n" is new line.
fclose($fh);
*/
Простой способ -
$data = array (
'aaa,bbb,ccc,dddd',
'123,456,789',
'"aaa","bbb"');
$fp = fopen('data.csv', 'wb');
foreach($data as $line){
$val = explode(",",$line);
fputcsv($fp, $val);
}
fclose($fp);
Таким образом, каждая строка массива $data будет переходить к новой строке вашего вновь созданного файла CSV. Работает только для PHP 5 и новее.
Вместо:
$query = "SELECT * FROM customers WHERE created>='{$start} 00:00:00' AND created<='{$end} 23:59:59' ORDER BY id";
$select_c = mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_array($select_c, MYSQL_ASSOC))
{
$result. = "{$row['email']},";
$result. = "\n";
echo $result;
}
Использовать:
$query = "SELECT * FROM customers WHERE created>='{$start} 00:00:00' AND created<='{$end} 23:59:59' ORDER BY id";
$select_c = mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_array($select_c, MYSQL_ASSOC))
{
echo implode(",", $row)."\n";
}
Поместите в переменную $output данные CSV и отобразите эхо с правильными заголовками.
header("Content-type: application/download\r\n");
header("Content-disposition: filename=filename.csv\r\n\r\n");
header("Content-Transfer-Encoding: ASCII\r\n");
header("Content-length: ".strlen($output)."\r\n");
echo $output;
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=file.csv");
function outputCSV($data) {
$output = fopen("php://output", "wb");
foreach ($data as $row)
fputcsv($output, $row); // here you can change delimiter/enclosure
fclose($output);
}
outputCSV(array(
array("name 1", "age 1", "city 1"),
array("name 2", "age 2", "city 2"),
array("name 3", "age 3", "city 3")
));
Больше людей должны это увидеть и проголосовать. Это лучший ответ на этой странице. PHP уже имеет встроенные функции для форматирования содержимого CSV. Их должен использовать каждый. Отличный ответ, @Andrey :)
Жаль, что fputcsv () не работает правильно :( bugs.php.net/bug.php?id=50686
Красиво, но функция outputCSV излишне усложняется. Вы можете просто foreach поверх $array, посылая его значения прямо в fputcsv. Не нужны эти __outputCSV и array_walk :) foreach($data as $vals) {fputcsv($filehandler,$vals);}
У меня возникли проблемы с французскими символами в массиве, потому что мне в конечном итоге нужно, чтобы файл .csv был открыт в Excel. Он задыхается от акцентированных символов. Такие вещи, как "Prévalence","age 1","city 1" Есть идеи? Возникновение с UTF-8 пока не помогло.
@Voodoo Как его открыть? Правильный способ - Data -> Get External Data -> From Text (Excel 2010, другие версии должны иметь аналогичный вариант).
@Voodoo Также вам не нужен Unicode, поскольку ANSI содержит символы с диакритическими знаками. И Excel должен открывать его даже без импорта. Какую версию Excel вы используете?
Не знаю почему, но в моем случае это не работает. Я беру строки из базы данных как while($row as mysql_fetch_array($res)){$data[] = $row;}. Кроме того, я не понимаю, для чего используется php://output.
Он не работает на localhost, но работает на размещенном сервере. Какой-либо причине? Кроме того, как я уже упоминал выше, значения добавляются дважды подряд.
Отлично работает в моей установке. Единственное изменение, которое мне нужно было сделать, это установить разделитель «;» для Excel, чтобы открыть его правильно
@theosem Delimiter зависит от настроек экспорта ОС или Excel. Я добавил примечание о разделителе.
Для строк следует использовать "вместо". Это безопаснее и дает бесконечно малое улучшение производительности.
@ danielson317 Чем безопаснее?
@andreyne Использование одинарных кавычек в первую очередь защищает от человеческой ошибки. Например, я хочу вывести «много $ money $» и забыть, что у меня есть переменная в области видимости, называемая $ money. Двойные кавычки, которые просто не нужны, теперь являются обязательством безопасности, если в $ money есть вводимые пользователем данные. В них много escape-последовательностей в двойных кавычках, поэтому, если вы намеренно не пользуетесь ими, безопаснее использовать одинарные кавычки для защиты от человеческой ошибки, которая является наиболее распространенной ошибкой в любом проекте программирования.
в случае laravel в файле csv я получаю два дополнительных пустых строки в начале
Самый простой способ - использовать выделенный CSV класс следующим образом:
$csv = new csv();
$csv->load_data(array(
array('name'=>'John', 'age'=>35),
array('name'=>'Adrian', 'age'=>23),
array('name'=>'William', 'age'=>57)
));
$csv->send_file('age.csv');
Я знаю, что эта ветка немного устарела, но для справок в будущем и для новичков, таких как я:
Все остальные здесь объясняют, как создать CSV, но упускают из виду основную часть вопроса: как связать. Чтобы сделать ссылку на загрузку CSV-файла, вы просто создаете ссылку на .php-файл, который, в свою очередь, отвечает как .csv-файл. Заголовки PHP делают это. Это позволяет делать интересные вещи, например добавлять переменные в строку запроса и настраивать вывод:
<a href = "my_csv_creator.php?user=23&othervariable=true">Get CSV</a>
my_csv_creator.php может работать с переменными, указанными в строке запроса, и, например, использовать различные или настроенные запросы к базе данных, изменять столбцы CSV, персонализировать имя файла и так далее, например:
User_John_Doe_10_Dec_11.csv
Э-э - любой, кто читает это, ОЧЕНЬ осторожен с таким подходом. Я готов поспорить, что входные данные не экранируются должным образом, и это может привести к большим дырам в безопасности в вашем приложении.
Его метод очень безопасен и отлично работает. Вы можете легко контролировать доступ с помощью сеанса, а также можете хранить всю информацию, которую хотите поместить в csv, в переменную сеанса. Затем просто отключите его как часть процесса преобразования в CSV. Я бы просто предложил использовать переменные сеанса вместо строки запроса.
В этом методе нет никаких дыр в безопасности как таковых. Пока указанный файл php выполняет свою работу по очистке и проверке доступа. Но показывать все это здесь не имеет смысла. Суть сообщения в том, что вы можете ссылаться на любой URL-адрес, генерирующий csv.
Вот улучшенная версия функции с php.net, которую опубликовал @Andrew.
function download_csv_results($results, $name = NULL)
{
if ( ! $name)
{
$name = md5(uniqid() . microtime(TRUE) . mt_rand()). '.csv';
}
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename='. $name);
header('Pragma: no-cache');
header("Expires: 0");
$outstream = fopen("php://output", "wb");
foreach($results as $result)
{
fputcsv($outstream, $result);
}
fclose($outstream);
}
Он действительно прост в использовании и отлично работает с наборами результатов MySQL (i) / PDO.
download_csv_results($results, 'your_name_here.csv');
Не забудьте указать exit() после этого вызова, если вы закончили со страницей.
Как изменить разделитель с, на; ?
как нам добавить кнопку для запуска этого события, чтобы пользователь мог загружать файл CSV по запросу?
У меня будет ошибка "SyntaxError: Unexpected token ILLEGAL" со строкой "fopen (" php: // output "," w ");" Когда я меняю его на "$ fp = fopen ('stats.csv', 'w');" это не показывает ошибку. Но тогда, конечно, это не работает. Как мне решить эту проблему?
@CanCeylan, это самостоятельный вопрос, и мне нужно больше деталей для его решения.
Сначала для упрощения вместо вызова с помощью кнопки и javascript. Я просто вызываю функцию download_csv_results. Однако он записывает весь контент на экран, он не загружает ни одного файла?
Добавьте fputcsv($outstream, array_keys($results[0])); непосредственно перед foreach, чтобы также включить заголовки столбцов.
Как писать в CSV-файл с помощью PHP-скрипта? На самом деле я тоже искал это. С PHP это довольно простая задача. fputs (handler, content) - у меня эта функция работает эффективно. Сначала вам нужно открыть файл, в который нужно записать контент, с помощью fopen ($ CSVFileName, «wb»).
$CSVFileName = “test.csv”;
$fp = fopen($CSVFileName, ‘wb’);
//Multiple iterations to append the data using function fputs()
foreach ($csv_post as $temp)
{
$line = “”;
$line .= “Content 1″ . $comma . “$temp” . $comma . “Content 2″ . $comma . “16/10/2012″.$comma;
$line .= “\n”;
fputs($fp, $line);
}
Всегда рекомендуется добавлять код в него, а не связывать его, поскольку ссылки имеют тенденцию меняться или исчезать с течением времени.
Ваш ответ на очень старую ветку. В то время как в 2008 году стандартной практикой было создание собственных строк, разделенных запятыми, правильным методом, начиная с PHP 5.1.0, было использование встроенной функции fputcsv (php.net/fputcsv). Будьте внимательны при чтении старых тем, чтобы убедиться, что информация, содержащаяся в них, по-прежнему актуальна.
Уже пришло очень хорошее решение. Я просто помещаю общий код, чтобы новичок получил полную помощь
<?php
extract($_GET); //you can send some parameter by query variable. I have sent table name in *table* variable
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=$table.csv");
header("Pragma: no-cache");
header("Expires: 0");
require_once("includes/functions.php"); //necessary mysql connection functions here
//first of all I'll get the column name to put title of csv file.
$query = "SHOW columns FROM $table";
$headers = mysql_query($query) or die(mysql_error());
$csv_head = array();
while ($row = mysql_fetch_array($headers, MYSQL_ASSOC))
{
$csv_head[] = $row['Field'];
}
echo implode(",", $csv_head)."\n";
//now I'll bring the data.
$query = "SELECT * FROM $table";
$select_c = mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_array($select_c, MYSQL_ASSOC))
{
foreach ($row as $key => $value) {
//there may be separator (here I have used comma) inside data. So need to put double quote around such data.
if (strpos($value, ',') !== false || strpos($value, '"') !== false || strpos($value, "\n") !== false) {
$row[$key] = '"' . str_replace('"', '""', $value) . '"';
}
}
echo implode(",", $row)."\n";
}
?>
Я сохранил этот код в csv-download.php
Теперь посмотрим, как я использовал эти данные для загрузки файла csv.
<a href = "csv-download.php?table=tbl_vfm"><img title = "Download as Excel" src = "images/Excel-logo.gif" alt = "Download as Excel" /><a/>
Поэтому, когда я щелкнул ссылку, он загрузил файл, не переходя на страницу csv-download.php в браузере.
Эй, это работает очень хорошо .... !!!! Спасибо Питеру Мортенсену и Коннору Бертону
<?php
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=file.csv");
header("Pragma: no-cache");
header("Expires: 0");
ini_set('display_errors',1);
$private=1;
error_reporting(E_ALL ^ E_NOTICE);
mysql_connect("localhost", "user", "pass") or die(mysql_error());
mysql_select_db("db") or die(mysql_error());
$start = $_GET["start"];
$end = $_GET["end"];
$query = "SELECT * FROM customers WHERE created>='{$start} 00:00:00' AND created<='{$end} 23:59:59' ORDER BY id";
$select_c = mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_array($select_c, MYSQL_ASSOC))
{
$result. = "{$row['email']},";
$result. = "\n";
echo $result;
}
?>
Использует ли НЕТ этот код в продакшене, он уязвим для SQL-инъекций
В дополнение ко всему уже сказанному вам может потребоваться добавить:
header("Content-Transfer-Encoding: UTF-8");
Это очень полезно при работе с файлами с несколькими языками, такими как имена людей или города.
Вот полный рабочий пример с использованием PDO и заголовками столбцов:
$query = $pdo->prepare('SELECT * FROM test WHERE id=?');
$query->execute(array($id));
$results = $query->fetchAll(PDO::FETCH_ASSOC);
download_csv_results($results, 'test.csv');
exit();
function download_csv_results($results, $name)
{
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename='. $name);
header('Pragma: no-cache');
header("Expires: 0");
$outstream = fopen("php://output", "wb");
fputcsv($outstream, array_keys($results[0]));
foreach($results as $result)
{
fputcsv($outstream, $result);
}
fclose($outstream);
}
Вы можете просто записать свои данные в CSV с помощью функции fputcsv. давайте посмотрим на пример ниже. Записать массив списка в файл CSV
$list[] = array("Cars", "Planes", "Ships");
$list[] = array("Car's2", "Planes2", "Ships2");
//define headers for CSV
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=file_name.csv');
//write data into CSV
$fp = fopen('php://output', 'wb');
//convert data to UTF-8
fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
foreach ($list as $line) {
fputcsv($fp, $line);
}
fclose($fp);
Написание собственного кода CSV, вероятно, является пустой тратой вашего времени, просто используйте такой пакет, как league / csv - он справляется со всеми сложными вещами за вас, документация хороша, и она очень стабильна / надежна:
Вам нужно будет использовать композитор. Если вы не знаете, какой композитор, я настоятельно рекомендую вам взглянуть: https://getcomposer.org/
обратите внимание, что правила для CSV важны. Чтобы обеспечить хорошее отображение, заключите поля в двойные кавычки и не забудьте заменить двойные кавычки внутри полей на двойные двойные кавычки: `echo '"' .str_replace ('"', '" "', $ record1). '","'. str_replace ....