Tạo tệp CSV cho người dùng bằng PHP


220

Tôi có dữ liệu trong cơ sở dữ liệu MySQL. Tôi đang gửi cho người dùng một URL để lấy dữ liệu của họ dưới dạng tệp CSV.

Tôi có e-mail của liên kết, truy vấn MySQL, vv được bảo hiểm.

Làm thế nào tôi có thể, khi họ nhấp vào liên kết, có một cửa sổ bật lên để tải xuống CVS với bản ghi từ MySQL?

Tôi có tất cả các thông tin để có được hồ sơ. Tôi chỉ không thấy làm thế nào để PHP tạo tệp CSV và cho phép họ tải xuống một tệp có phần mở rộng .csv.

Câu trả lời:


280

Thử:

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;

Vân vân

Chỉnh sửa: Đây là một đoạn mã tôi sử dụng để mã hóa tùy chọn các trường CSV:

function maybeEncodeCSVField($string) {
    if(strpos($string, ',') !== false || strpos($string, '"') !== false || strpos($string, "\n") !== false) {
        $string = '"' . str_replace('"', '""', $string) . '"';
    }
    return $string;
}

11
lưu ý các quy tắc cho CSV rất quan trọng. Để đảm bảo hiển thị tốt, hãy đặt doublequote xung quanh các trường của bạn và đừng quên thay thế dấu ngoặc kép bên trong các trường thành dấu ngoặc kép: `echo '"' .str numplace ('"', '" "', $ record1). '","'. str numplace ....
Mala

46
Chỉ cần làm rõ, tiêu đề Kiểu nội dung HTTP chính xác cho CSV là văn bản / csv, không phải ứng dụng / csv. Tôi nghi ngờ bất kỳ trình duyệt hiện đại nào cũng sẽ quan tâm, nhưng vì có những tiêu chuẩn nên chúng tôi cũng có thể sử dụng chúng.
fentie

10
Nói chung, vui lòng theo RFC 4180 khi tạo tệp CSV. tools.ietf.org/html/rfc4180
Oleg Barshay

5
@Oleg Barshay: OMG, RFC là một tác phẩm chính: "Nếu trích dẫn kép được sử dụng để bao quanh các trường, thì một trích dẫn kép xuất hiện bên trong một trường phải được thoát bằng cách đặt trước nó bằng một trích dẫn kép khác.". KHÁC NHÂN ĐÔI-NHANH CHÓNG!
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: // đầu ra
fputcsv


64
Nhiều người cần phải xem điều này và bỏ phiếu lên. Đây dễ dàng là câu trả lời tốt nhất trên trang này. PHP đã có các hàm dựng sẵn để định dạng nội dung CSV. Mọi người nên sử dụng chúng. Câu trả lời tuyệt vời, @Andrey :)
maček

2
Quá xấu fputcsv () không hoạt động chính xác mặc dù :( bug.php.net/orms.php?id=50686
gou1

4
Đẹp, nhưng outputCSVchức năng là không cần thiết phức tạp. Bạn chỉ có thể foreachhơn $array, gửi giá trị của nó thẳng vào fputcsv. Không cần điều đó __outputCSVarray_walk:)foreach($data as $vals) {fputcsv($filehandler,$vals);}
Sygmoral

Tôi gặp một số vấn đề với các ký tự tiếng Pháp trong mảng vì cuối cùng tôi cần .csv được mở trong Excel. Nó bóp nghẹt các ký tự có dấu. Những điều như "Prévalence","age 1","city 1" bất kỳ ý tưởng? Lộn xộn với UTF-8 đã không giúp được gì cho đến nay.
Voodoo

1
@theosem Dấu phân cách phụ thuộc vào cài đặt xuất OS hoặc Excel. Tôi đã thêm ghi chú về dấu phân cách.
Andrii Nemchenko

19

Đây là phiên bản cải tiến của chức năng từ php.net mà @Andrew đã đăng.

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

Nó thực sự dễ sử dụng và hoạt động tuyệt vời với các tập kết quả MySQL (i) / PDO.

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

Hãy nhớ exit()sau khi gọi điều này nếu bạn đã hoàn thành với trang.


Làm thế nào để bạn thay đổi dấu phân cách từ, sang; ?
Grumpy

1
Làm thế nào chúng ta nên thêm một nút, để kích hoạt sự kiện này, để người dùng có thể tải xuống tệp CSV theo yêu cầu?
CanCeylan

Tôi sẽ gặp lỗi "SyntaxError: Mã thông báo bất ngờ" với dòng "fopen (" php: // output "," w ");" Khi tôi thay đổi thành "$ fp = fopen ('stats.csv', 'w');" nó không hiển thị lỗi. Nhưng tất nhiên sau đó nó không hoạt động. Tôi nên giải quyết nó như thế nào?
CanCeylan

@CanCeylan, Đó là một câu hỏi theo đúng nghĩa của nó và tôi cần thêm chi tiết để giải quyết nó.
Xeoncross

1
Thêm fputcsv($outstream, array_keys($results[0]));ngay trước khi bạn foreachcũng bao gồm các tiêu đề cột.
Justin

16

Ngoài tất cả những gì đã nói, bạn có thể cần thêm:

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

Nó rất hữu ích khi xử lý các tệp có nhiều ngôn ngữ trong đó, như tên của mọi người hoặc thành phố.


9

Chủ đề này hơi cũ, tôi biết, nhưng để tham khảo trong tương lai và cho noobs như tôi:

Mọi người khác ở đây giải thích cách tạo CSV, nhưng bỏ lỡ một phần cơ bản của câu hỏi: cách liên kết. Để liên kết để tải xuống tệp CSV, bạn chỉ cần liên kết đến tệp .php, lần lượt trả lời là tệp .csv. Các tiêu đề PHP làm điều đó. Điều này cho phép các công cụ tuyệt vời, như thêm các biến vào chuỗi truy vấn và tùy chỉnh đầu ra:

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

my_csv_creator.php có thể hoạt động với các biến được đưa ra trong chuỗi truy vấn và ví dụ sử dụng các truy vấn cơ sở dữ liệu khác nhau hoặc tùy chỉnh, thay đổi các cột của CSV, cá nhân hóa tên tệp, v.v.

User_John_Doe_10_Dec_11.csv

1
Uh - bất cứ ai đọc điều này đều RẤT cảnh giác với phương pháp này. Tôi cá rằng các đầu vào không được thoát đúng và điều này có thể dẫn đến các lỗ hổng bảo mật lớn trong ứng dụng của bạn.
calumbrodie

Phương pháp của anh ấy rất an toàn, và nó hoạt động rất tốt. Bạn có thể dễ dàng kiểm soát quyền truy cập với phiên và bạn cũng có thể lưu trữ tất cả thông tin bạn muốn đưa vào một csv trong một phiên var. Sau đó, chỉ cần bỏ đặt nó là một phần của quá trình chuyển đổi nó thành một csv. Tôi chỉ đề nghị sử dụng vars phiên thay vì chuỗi truy vấn.
inorganik

1
Không có lỗ hổng bảo mật cho mỗi phương pháp này. Miễn là tệp php được tham chiếu đang thực hiện công việc kiểm tra truy cập và vệ sinh. Nhưng nó không thực sự có ý nghĩa để hiển thị tất cả những điều đó ở đây. Điểm của bài viết là bạn có thể liên kết với bất kỳ url nào tạo csv.
danielson317 3/03/2015

8

Tạo tệp của bạn sau đó trả về một tham chiếu đến nó với tiêu đề chính xác để kích hoạt Lưu dưới dạng - chỉnh sửa các mục sau nếu cần. Đặt dữ liệu CSV của bạn vào $ 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);

1
Sử dụng Xử lý nội dung "nội tuyến" có nghĩa là trình duyệt sẽ cố gắng hiển thị nó mà không cần tải xuống (IE có xu hướng nhúng một phiên bản Excel cho điều đó). "tập tin đính kèm" là những gì cần thiết để buộc tải xuống.
Gert van den Berg

5

Dưới đây là một ví dụ hoạt động đầy đủ bằng cách sử dụng PDO và bao gồm các tiêu đề cột:

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

4

Trước tiên, tạo dữ liệu dưới dạng Chuỗi với dấu phẩy là dấu phân cách (được phân tách bằng ","). Một cái gì đó như thế này

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

3

Này nó hoạt động rất tốt .... !!!! Cảm ơn Peter Mortensen và 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;
}

?>


Đừng KHÔNG sử dụng mã này trong sản xuất, nó là dễ bị tổn thương để tiêm SQL
ntzm

2

Phương pháp đơn giản -

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

Vì vậy, mỗi dòng của $datamảng sẽ chuyển đến một dòng mới của tệp CSV mới tạo của bạn. Nó chỉ hoạt động cho PHP 5 trở lên.


2

Bạn chỉ có thể ghi dữ liệu của mình vào CSV bằng chức năng fputcsv . chúng ta hãy xem ví dụ dưới đây Viết mảng danh sách vào tệp 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);

1

Cách dễ nhất là sử dụng lớp CSV chuyên dụng như thế này:

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

1

Thay vì:

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

Sử dụng:

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

1

Đã có giải pháp rất tốt đã đến. Tôi chỉ đặt tổng số mã để người mới nhận được tổng số trợ giúp

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

?>

Tôi đã lưu mã này trong csv-download.php

Bây giờ hãy xem cách tôi đã sử dụng dữ liệu này để tải xuống tệp csv

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

Vì vậy, khi tôi đã nhấp vào liên kết, nó tải xuống tệp mà không đưa tôi đến trang csv-download.php trên trình duyệt.


0

Để gửi nó dưới dạng CSV và đặt tên tệp, sử dụng tiêu đề ():

http://us2.php.net/header

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

Theo như tự tạo CSV, bạn chỉ cần lặp qua tập kết quả, định dạng đầu ra và gửi nó, giống như bất kỳ nội dung nào khác.


0

Viết mã CSV của riêng bạn có thể là một sự lãng phí thời gian của bạn, chỉ cần sử dụng một gói như giải đấu / csv - nó xử lý tất cả những thứ khó khăn cho bạn, tài liệu tốt và rất ổn định / đáng tin cậy:

http://csv.thephpleague.com /

Bạn sẽ cần phải sử dụng nhà soạn nhạc. Nếu bạn không biết nhà soạn nhạc nào thì tôi khuyên bạn nên xem qua: https://getcomposer.org/


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

0

Làm cách nào để ghi vào tệp CSV bằng tập lệnh PHP? Thật ra tôi cũng đang tìm kiếm điều đó. Đây là một loại nhiệm vụ dễ dàng với PHP. fputs (handler, content) - chức năng này hoạt động hiệu quả với tôi. Trước tiên, bạn cần mở tệp mà bạn cần viết nội dung bằng 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);
}

Nó luôn được ưu tiên để thêm mã vào chính nó thay vì liên kết, vì các liên kết có xu hướng thay đổi hoặc biến mất theo thời gian.
Sgoettschkes

Câu trả lời của bạn là một chủ đề rất cũ. Trong khi năm 2008, đó là tiêu chuẩn thực hiện để xây dựng dấu phẩy của riêng bạn tách dòng, phương pháp đúng kể từ PHP 5.1.0 sẽ được sử dụng xây dựng trong chức năng fputcsv ( php.net/fputcsv ). Cẩn thận khi đọc các chủ đề cũ để đảm bảo rằng thông tin trong đó vẫn có liên quan.
Luke Mills

-1

Đặt vào $outputbiến dữ liệu CSV và echo với các tiêu đề chính xác

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.