Как создать и скачать файл csv из php скрипта?

89

Я начинающий программист и много искал по своему вопросу, но не смог найти полезного решения или руководства по этому поводу.

Моя цель - у меня есть массив PHP, и элементы массива отображаются в списке на странице.

Я хочу добавить опцию, чтобы при желании пользователь мог создать файл CSV с элементами массива и загрузить его.

Я не знаю, как это сделать. Я тоже много искал. Но пока не удалось найти какой-либо полезный ресурс.

Пожалуйста, предоставьте мне какое-нибудь учебное пособие, решение или совет, чтобы реализовать его самостоятельно. Поскольку я новичок, пожалуйста, предоставьте простые в реализации решения.

Мой массив выглядит так:

Array
(
    [0] => Array
        (
            [fs_id] => 4c524d8abfc6ef3b201f489c
            [name] => restaurant
            [lat] => 40.702692
            [lng] => -74.012869
            [address] => new york
            [postalCode] => 
            [city] => NEW YORK
            [state] => ny
            [business_type] => BBQ Joint
            [url] => 
        )

)
user2302780
источник
2
phpExcel для файла CSV - это многовато .. php.net/manual/en/function.fputcsv.php
Дэмиен Пирси
Покажите структуру вашего массива, и я могу предоставить код для преобразования элементов в CSV
наполовину быстро
@ Half-Fast Я добавил структуру массива в пост
user2302780
2
как добавить заголовок столбца в файл csv?
user2302780
возможный дубликат экспорта в CSV через PHP
Михал Мау

Ответы:

200

Вы можете использовать встроенную функцию fputcsv () для ваших массивов, чтобы генерировать правильные строки csv из вашего массива, поэтому вам придется перебирать и собирать строки, например:

$f = fopen("tmp.csv", "w");
foreach ($array as $line) {
    fputcsv($f, $line);
}

Чтобы браузеры предлагали диалоговое окно «Сохранить как», вам нужно будет отправить такие заголовки HTTP (подробнее об этом заголовке см. В RFC ):

header('Content-Disposition: attachment; filename="filename.csv";');

Собираем все вместе:

function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
    // open raw memory as file so no temp files needed, you might run out of memory though
    $f = fopen('php://memory', 'w'); 
    // loop over the input array
    foreach ($array as $line) { 
        // generate csv lines from the inner arrays
        fputcsv($f, $line, $delimiter); 
    }
    // reset the file pointer to the start of the file
    fseek($f, 0);
    // tell the browser it's going to be a csv file
    header('Content-Type: application/csv');
    // tell the browser we want to save it instead of displaying it
    header('Content-Disposition: attachment; filename="'.$filename.'";');
    // make php send the generated csv lines to the browser
    fpassthru($f);
}

И вы можете использовать это так:

array_to_csv_download(array(
  array(1,2,3,4), // this array is going to be the first row
  array(1,2,3,4)), // this array is going to be the second row
  "numbers.csv"
);

Обновление:
вместо этого php://memoryвы также можете использовать php://outputдескриптор файла и отказаться от поиска и т.Д.

function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
    header('Content-Type: application/csv');
    header('Content-Disposition: attachment; filename="'.$filename.'";');

    // open the "output" stream
    // see http://www.php.net/manual/en/wrappers.php.php#refsect2-wrappers.php-unknown-unknown-unknown-descriptioq
    $f = fopen('php://output', 'w');

    foreach ($array as $line) {
        fputcsv($f, $line, $delimiter);
    }
}   
сложный857
источник
2
почему не echoсгенерированные строки CSV прямо в цикле?
Alex Shesterov
1
@AlexShesterov, основная причина в том, что fputcsv()не возвращает сгенерированную строку, ей понадобится файловый дескриптор для записи. Вы можете перематывать, писать, очищать буфер на каждой итерации, если у вас ограниченная память. Или просто используйте вместо этого настоящий временный файл.
complex857
@ complex857 как добавить заголовок столбца для CSV?
user2302780
@ user2302780: Вы просто добавляете к своим данным строку с именами столбцов. Вы можете использовать ключи из массивов данных с чем-то вроде$data = array_merge(array(array_keys($data[0])), $data);
complex857
1
@JoseRojas, этого и следовало ожидать, поскольку, как только вы что-то наденете на провод (то, что концептуально означает вывод вещей с помощью php), вы не можете вернуться к этому. Чтобы использовать, php://outputсм. Второй обновленный образец кода.
complex857 07
18

У меня недостаточно репутации, чтобы отвечать на решение @ complex857. Работает отлично, но пришлось добавить; в конце заголовка Content-Disposition. Без него браузер добавляет два дефиса в конце имени файла (например, вместо «export.csv» файл сохраняется как «export.csv--»). Вероятно, он пытается очистить \ r \ n в конце строки заголовка.

Правильная линия должна выглядеть так:

header('Content-Disposition: attachment;filename="'.$filename.'";');

Если в CSV есть символы UTF-8, вам необходимо изменить кодировку на UTF-8, изменив строку Content-Type:

header('Content-Type: application/csv; charset=UTF-8');

Кроме того, мне кажется более элегантным использовать rewind () вместо fseek ():

rewind($f);

Спасибо за решение!

Luxian
источник
2
Я сам никогда не сталкивался с заключением --в конце имен файлов, однако я обновил ответ (почему бы просто не отправить правку?)
complex857
14

Попробуй ... csv скачать.

<?php 
mysql_connect('hostname', 'username', 'password');
mysql_select_db('dbname');
$qry = mysql_query("SELECT * FROM tablename");
$data = "";
while($row = mysql_fetch_array($qry)) {
  $data .= $row['field1'].",".$row['field2'].",".$row['field3'].",".$row['field4']."\n";
}

header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="filename.csv"');
echo $data; exit();
?>
Индраджит Сингх
источник
сломается, если значение поля содержит, поэтому я предпочитаю tsv (табуляция встречается реже, и мы можем заменить ее или что-то в этом роде)
Ориадам
14

Это функция, которую я использовал в своем проекте, и она работает должным образом.

function array_csv_download( $array, $filename = "export.csv", $delimiter=";" )
{
    header( 'Content-Type: application/csv' );
    header( 'Content-Disposition: attachment; filename="' . $filename . '";' );

    // clean output buffer
    ob_end_clean();

    $handle = fopen( 'php://output', 'w' );

    // use keys as column titles
    fputcsv( $handle, array_keys( $array['0'] ) );

    foreach ( $array as $value ) {
        fputcsv( $handle, $value , $delimiter );
    }

    fclose( $handle );

    // flush buffer
    ob_flush();

    // use exit to get rid of unexpected output afterward
    exit();
}
Саджидур Рахман
источник
1
Мне было трудно реализовать его в wordpress send_headers, потому что каждый раз, когда он добавляет всю текущую страницу html в конец файла csv. Эти ответы меня сильно удивляют, но я использую их без операций с буферами.
Олег Апанович
чистый буфер вывода решил для меня проблему, что до использования этих строк кода в начале и в конце сформированного файла были пустые строки.
Шарунас Бельскис
8

Используйте приведенный ниже код для преобразования массива php в CSV

<?php
   $ROW=db_export_data();//Will return a php array
   header("Content-type: application/csv");
   header("Content-Disposition: attachment; filename=test.csv");
   $fp = fopen('php://output', 'w');

   foreach ($ROW as $row) {
        fputcsv($fp, $row);
   }
   fclose($fp);
Киран Редди
источник
3

Если ваша структура массива всегда будет многомерной именно таким образом, тогда мы можем перебирать элементы следующим образом:

$fh = fopen('somefile.csv', 'w') or die('Cannot open the file');

for( $i=0; $i<count($arr); $i++ ){
    $str = implode( ',', $arr[$i] );
    fwrite( $fh, $str );
    fwrite( $fh, "\n" );
}
fclose($fh);

Это один из способов сделать это ... вы можете сделать это вручную, но этот способ быстрее и проще для понимания и чтения.

Затем вы управляете своими заголовками, как это делает комплекс857, чтобы выплюнуть файл. Затем вы можете удалить файл с помощью unlink (), если он вам больше не нужен, или оставить его на сервере, если хотите.

наполовину быстрый
источник
-2

Используйте следующее,

echo "<script type='text/javascript'> window.location.href = '$file_name'; </script>";
Ашвин Балани
источник