Як створити та завантажити файл 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] => 
        )

)

2
phpExcel для файлу CSV трохи забагато .. php.net/manual/en/function.fputcsv.php
Damien Pirsy

Покажіть свою матричну структуру і I C забезпечити деякий код , щоб включити елементи в 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);
    }
}   

2
чому б не echoзгенеровані CSV-рядки безпосередньо в циклі?
Алекс Шестеров,

1
@AlexShesterov, головна причина полягає в тому, що fputcsv()не повертає згенерований рядок, йому знадобиться дескриптор файлу для запису. Ви можете перемотати назад, записати, очистити буфер на кожній ітерації, хоча, якщо пам'ять обмежена. Або просто використовуйте справжній тимчасовий файл.
complex857

@ complex857 як я можу додати заголовок стовпця для csv?
user2302780

@ user2302780: Ви просто додаєте до даних рядок імен стовпців. Ви можете використовувати клавіші з масивів даних чимось на зразок$data = array_merge(array(array_keys($data[0])), $data);
complex857

1
@JoseRojas, чого слід очікувати, оскільки, коли ви щось ставите по дроту (що те, що виводить речі за допомогою php, означає концептуально), ви не можете повернутися до цього. Для використання php://outputдив. Другий оновлений зразок коду.
complex857

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);

Дякуємо за ваше рішення!


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 (вкладка рідше, ніж, і ми можемо її замінити або щось інше)
oriadam

13

Це функція, яку я використав для свого проекту, і вона працює як слід.

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 hook, тому що кожного разу, коли він додає всю поточну сторінку 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);

Це один із способів зробити це ... Ви можете зробити це вручну, але таким чином швидше та простіше зрозуміти та прочитати.

Тоді ви керували б своїми заголовками тим, що робить complex857, щоб виплюнути файл. Потім ви можете видалити файл за допомогою unlink (), якщо він вам більше не потрібен, або ви можете залишити його на сервері, якщо хочете.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.