Buat File CSV untuk pengguna di PHP

220

Saya punya data di database MySQL. Saya mengirimkan URL kepada pengguna untuk mengeluarkan data mereka sebagai file CSV.

Saya memiliki e-mail tautan, permintaan MySQL, dll. Tertutup.

Bagaimana saya, ketika mereka mengklik tautan, memiliki pop-up untuk mengunduh CVS dengan catatan dari MySQL?

Saya memiliki semua informasi untuk mendapatkan catatan. Saya hanya tidak melihat bagaimana membuat PHP membuat file CSV dan membiarkan mereka mengunduh file dengan ekstensi .csv.

d -_- b
sumber

Jawaban:

280

Mencoba:

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;

dll

Sunting: Berikut cuplikan kode yang saya gunakan untuk menyandikan bidang CSV secara opsional:

function maybeEncodeCSVField($string) {
    if(strpos($string, ',') !== false || strpos($string, '"') !== false || strpos($string, "\n") !== false) {
        $string = '"' . str_replace('"', '""', $string) . '"';
    }
    return $string;
}
Oleg Barshay
sumber
11
perhatikan aturan untuk CSV itu penting. Untuk memastikan tampilan yang bagus, letakkan tanda kutip ganda di sekitar bidang Anda, dan jangan lupa untuk mengganti tanda kutip ganda di dalam bidang menjadi tanda kutip ganda: `echo '"' .str_replace ('"', '" ",' $ record1). '","'. str_replace ....
Mala
46
Hanya untuk memperjelas, header Jenis Konten HTTP yang benar untuk CSV adalah teks / csv, bukan aplikasi / csv. Saya ragu peramban modern mana pun akan peduli, tetapi karena ada standar kami mungkin juga menggunakannya.
fentie
10
Secara umum, harap ikuti RFC 4180 saat membuat file CSV. tools.ietf.org/html/rfc4180
Oleg Barshay
5
@Oleg Barshay: OMG, bahwa RFC adalah karya utama: "Jika tanda kutip ganda digunakan untuk menyertakan bidang, maka tanda kutip ganda yang muncul di dalam bidang harus diloloskan dengan mendahului dengan tanda kutip ganda lainnya.". QUOTE DOUBLE LAINNYA!
aefxx
465
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: // output
fputcsv

Andrii Nemchenko
sumber
64
Lebih banyak orang perlu melihat ini dan memilihnya. Ini dengan mudah jawaban terbaik di halaman ini. PHP sudah memiliki fungsi bawaan untuk memformat konten CSV. Setiap orang harus menggunakannya. Jawaban yang bagus, @Andrey :)
maček
2
Sayangnya fputcsv () tidak berfungsi dengan benar :( bugs.php.net/bug.php?id=50686
gou1
4
Bagus, tetapi outputCSVfungsinya tidak perlu rumit. Anda bisa foreachberakhir $array, mengirimkan nilainya langsung ke fputcsv. Tidak perlu untuk itu __outputCSVdan array_walk:)foreach($data as $vals) {fputcsv($filehandler,$vals);}
Sygmoral
Saya mengalami beberapa masalah dengan karakter Prancis dalam array karena saya akhirnya perlu .csv terbuka di Excel. Ini tersedak karakter beraksen. Hal-hal seperti "Prévalence","age 1","city 1" Ada ide? Messing dengan UTF-8 sejauh ini tidak membantu.
Voodoo
1
Pembatas @theosem tergantung pada pengaturan ekspor OS atau Excel. Saya telah menambahkan catatan tentang pembatas.
Andrii Nemchenko
19

Ini adalah versi perbaikan fungsi dari php.net yang diposting oleh @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);
}

Sangat mudah digunakan dan bekerja sangat baik dengan set hasil MySQL (i) / PDO.

download_csv_results($results, 'your_name_here.csv');

Ingat untuk exit()setelah menelepon ini jika Anda selesai dengan halaman.

Xeoncross
sumber
Bagaimana Anda mengubah pemisah dari, ke; ?
Grumpy
1
bagaimana kita menambahkan tombol, untuk memicu acara ini, sehingga pengguna dapat mengunduh file CSV sesuai permintaan?
CanCeylan
Saya akan memiliki kesalahan "SyntaxError: Unken token ILLEGAL" dengan baris "fopen (" php: // output "," w ");" Ketika saya mengubahnya ke "$ fp = fopen ('stats.csv', 'w');" itu tidak menunjukkan kesalahan. Tapi tentu saja itu tidak berhasil. Bagaimana saya harus menyelesaikannya?
CanCeylan
@CanCeylan, Itu adalah pertanyaan di dalamnya sendiri dan saya perlu lebih banyak detail untuk menyelesaikannya.
Xeoncross
1
Tambahkan fputcsv($outstream, array_keys($results[0]));tepat sebelum Anda foreachjuga sertakan tajuk kolom.
Justin
16

Selain semua yang sudah dikatakan, Anda mungkin perlu menambahkan:

header("Content-Transfer-Encoding: UTF-8");

Ini sangat berguna saat menangani file dengan banyak bahasa di dalamnya, seperti nama orang, atau kota.

Stan
sumber
9

Utasnya agak tua, saya tahu, tetapi untuk referensi di masa depan dan untuk noobs seperti saya:

Semua orang di sini menjelaskan cara membuat CSV, tetapi kehilangan bagian dasar dari pertanyaan: cara menautkan. Untuk menautkan unduhan file CSV, Anda cukup menautkan file .php, yang pada gilirannya merespons sebagai file .csv. Header PHP melakukan itu. Ini memungkinkan hal-hal keren, seperti menambahkan variabel ke querystring dan menyesuaikan output:

<a href="my_csv_creator.php?user=23&amp;othervariable=true">Get CSV</a>

my_csv_creator.php dapat bekerja dengan variabel yang diberikan dalam querystring dan misalnya menggunakan kueri basis data yang berbeda atau yang disesuaikan, mengubah kolom CSV, mempersonalisasikan nama file dan sebagainya, misalnya:

User_John_Doe_10_Dec_11.csv
LBJ
sumber
1
Uh - siapa pun yang membaca ini SANGAT waspada dengan pendekatan ini. Saya ingin bertaruh bahwa input tidak dapat diloloskan dengan benar dan ini dapat menyebabkan lubang keamanan besar dalam aplikasi Anda.
calumbrodie
Metodenya sangat aman, dan itu bekerja dengan baik. Anda dapat dengan mudah mengontrol akses dengan sesi, dan Anda juga dapat menyimpan semua informasi yang ingin Anda masukkan ke dalam csv di sesi var. Kemudian hapus saja sebagai bagian dari proses mengubahnya menjadi csv. Saya hanya menyarankan menggunakan vars sesi alih-alih string kueri.
inorganik
1
Tidak ada lubang keamanan per se dengan metode ini. Selama file php direferensikan melakukan pekerjaan sanitasi dan pemeriksaan akses. Tetapi tidak masuk akal untuk menunjukkan semua itu di sini. Maksud dari posting ini adalah Anda dapat menautkan ke url apa pun yang menghasilkan csv.
danielson317
8

Buat file Anda lalu kembalikan referensi ke sana dengan tajuk yang benar untuk memicu Save As - edit yang berikut ini sesuai kebutuhan. Masukkan data CSV Anda ke $ 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);
typemismatch
sumber
1
Menggunakan "-line" Content-Disposition berarti bahwa browser harus berusaha untuk menunjukkannya tanpa mengunduh (IE cenderung menyematkan contoh Excel untuk itu). "lampiran" adalah apa yang diperlukan untuk memaksa unduhan.
Gert van den Berg
5

Berikut adalah contoh kerja lengkap menggunakan PDO dan termasuk tajuk kolom:

$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);
}
Justin
sumber
4

Pertama-tama buat data sebagai String dengan koma sebagai pembatas (dipisahkan dengan ","). Sesuatu seperti ini

$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);
*/
Behzad Ravanbakhsh
sumber
3

Hei ini bekerja dengan sangat baik .... !!!! Terima kasih Peter Mortensen dan Connor Burton

<?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;
}

?>

Kaddy
sumber
Apakah tidak menggunakan kode ini di produksi, itu rentan terhadap injeksi SQL
ntzm
2

Metode sederhana -

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

Jadi setiap baris $dataarray akan menuju ke baris baru dari file CSV yang baru Anda buat. Ini hanya berfungsi untuk PHP 5 dan yang lebih baru.

pengguna244641
sumber
2

Anda cukup menulis data Anda ke CSV menggunakan fungsi fputcsv . mari kita lihat contoh di bawah ini. Tulis larik daftar ke file 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);
Shahbaz
sumber
1

Cara termudah adalah dengan menggunakan kelas CSV khusus seperti ini:

$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'); 
Sergiu
sumber
1

Dari pada:

$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;
}

Menggunakan:

$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";
}
Joshua
sumber
1

Sudah solusi yang sangat bagus datang. Saya hanya memasukkan kode total sehingga pemula mendapat bantuan total

<?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";
}

?>

Saya telah menyimpan kode ini di csv-download.php

Sekarang lihat bagaimana saya menggunakan data ini untuk mengunduh file csv

<a href="csv-download.php?table=tbl_vfm"><img title="Download as Excel" src="images/Excel-logo.gif" alt="Download as Excel" /><a/>

Jadi ketika saya mengklik tautan itu mengunduh file tanpa membawa saya ke halaman csv-download.php di browser.

zahid9i
sumber
0

Untuk mengirimnya sebagai CSV dan memberikannya nama file, gunakan header ():

http://us2.php.net/header

header('Content-type: text/csv');
header('Content-disposition: attachment; filename="myfile.csv"');

Sejauh membuat CSV itu sendiri, Anda hanya akan mengulang set hasil, memformat output dan mengirimkannya, sama seperti Anda akan konten lainnya.

Gavin M. Roy
sumber
0

Menulis kode CSV Anda sendiri mungkin membuang-buang waktu Anda, cukup gunakan paket seperti league / csv - ini berkaitan dengan semua hal yang sulit bagi Anda, dokumentasinya bagus dan sangat stabil / dapat diandalkan:

http://csv.thephpleague.com/

Anda harus menggunakan komposer. Jika Anda tidak tahu apa itu komposer, saya sangat menyarankan Anda melihatnya: https://getcomposer.org/

John Hunt
sumber
0
<?
    // 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 );
?>
Vish00722
sumber
0

Bagaimana cara menulis dalam file CSV menggunakan skrip PHP? Sebenarnya saya juga mencari itu. Ini adalah jenis tugas yang mudah dengan PHP. fputs (handler, content) - fungsi ini bekerja secara efisien untuk saya. Pertama, Anda perlu membuka file di mana Anda perlu menulis konten menggunakan 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);
}
ntzm
sumber
Itu selalu disukai untuk menambahkan kode ke dalam dirinya sendiri daripada menautkan, karena tautan cenderung berubah atau menghilang seiring waktu.
Sgoettschkes
Jawaban Anda adalah utas yang sangat lama. Sementara pada 2008, itu adalah praktik standar untuk membangun garis yang dipisahkan koma Anda sendiri, metode yang benar karena PHP 5.1.0 akan menggunakan fungsi built in fputcsv ( php.net/fputcsv ). Berhati-hatilah saat membaca utas lama untuk memastikan bahwa informasi yang terkandung di dalamnya masih relevan.
Luke Mills
-1

Masukkan $outputvariabel data CSV dan gema dengan header yang benar

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;
Lorenzo Massacci
sumber