สร้างไฟล์ CSV สำหรับผู้ใช้ใน PHP


220

ฉันมีข้อมูลในฐานข้อมูล MySQL ฉันกำลังส่ง URL ให้ผู้ใช้เพื่อนำข้อมูลออกมาเป็นไฟล์ CSV

ฉันมีลิงก์ทางอีเมลแบบสอบถาม MySQL ฯลฯ ครอบคลุม

ฉันจะคลิกป๊อปอัพเพื่อดาวน์โหลด CVS พร้อมบันทึกจาก MySQL ได้อย่างไร

ฉันมีข้อมูลทั้งหมดที่จะได้รับการบันทึกแล้ว ฉันไม่เห็นวิธีการสร้าง PHP ไฟล์ CSV และให้พวกเขาดาวน์โหลดไฟล์ที่มีนามสกุล. csv

คำตอบ:


280

ลอง:

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

11
โปรดทราบว่ากฎสำหรับ CSV มีความสำคัญ เพื่อให้แน่ใจว่าการแสดงผลที่ดีวาง doublequotes รอบ ๆ ฟิลด์ของคุณและอย่าลืมแทนที่เครื่องหมายอัญประกาศคู่ภายในฟิลด์เป็น double-quote: `echo '"' .str_replace ('' ',' "'', $ record1) '","'. str_replace ....
Mala

46
เพื่อชี้แจงส่วนหัว HTTP เนื้อหาประเภทที่ถูกต้องสำหรับ CSV คือ text / csv ไม่ใช่ application / csv ฉันสงสัยว่าเบราว์เซอร์ที่ทันสมัยจะดูแลอย่างใดอย่างหนึ่ง แต่เนื่องจากมีมาตรฐานที่เราอาจใช้
fentie

10
โดยทั่วไปโปรดติดตาม RFC 4180 เมื่อสร้างไฟล์ CSV tools.ietf.org/html/rfc4180
Oleg Barshay

5
@Oleg Barshay: OMG, RFC นั้นเป็นผลงานชิ้นเอก: "ถ้าใช้ double-quotes เพื่อใส่ฟิลด์ดังนั้นการแสดง double-quote ที่ปรากฏในเขตข้อมูลจะต้องถูกหลีกเลี่ยงโดยนำหน้าด้วยเครื่องหมายคำพูดคู่อื่น" อีกสองเท่า - อ้าง!
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: // เอาต์พุต
fputcsv


64
ผู้คนจำนวนมากต้องเห็นสิ่งนี้และลงคะแนน นี่เป็นคำตอบที่ง่ายที่สุดในหน้านี้ PHP มีฟังก์ชันในตัวสำหรับการจัดรูปแบบเนื้อหา CSV แล้ว ทุกคนควรใช้พวกเขา คำตอบที่ดี @Andrey :)
MACEK

2
fputcsv ที่แย่เกินไป () ทำงานไม่ถูกต้องแม้ว่า :( bugs.php.net/bug.php?id=50686
gou1

4
ดี แต่outputCSVฟังก์ชั่นมีความซับซ้อนโดยไม่จำเป็น คุณก็สามารถforeachมากกว่าการส่งค่าของมันตรงเข้า$array fputcsvไม่มีความจำเป็นในการที่__outputCSVและarray_walk:)foreach($data as $vals) {fputcsv($filehandler,$vals);}
Sygmoral

ฉันมีปัญหากับตัวอักษรภาษาฝรั่งเศสในอาร์เรย์เพราะในที่สุดฉันก็ต้องใช้. csv เพื่อเปิดใน Excel มันฉายากับตัวละครที่ถูกเน้นเสียง สิ่งที่ชอบ"Prévalence","age 1","city 1" ความคิดใด ๆ การล้อเล่นกับ UTF-8 ยังไม่ได้ช่วย
วูดู

1
@theosem Delimiter ขึ้นอยู่กับการตั้งค่าการส่งออก OS หรือ Excel ฉันได้เพิ่มบันทึกย่อเกี่ยวกับตัวคั่นแล้ว
Andrii Nemchenko

19

นี่คือฟังก์ชั่นที่ปรับปรุงจาก 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()โทรหลังจากนี้ถ้าคุณทำกับหน้า


คุณเปลี่ยนตัวคั่นจากเป็นเป็นอย่างไร ?
พอใจ

1
เราควรเพิ่มปุ่มอย่างไรเพื่อกระตุ้นกิจกรรมนี้เพื่อให้ผู้ใช้สามารถดาวน์โหลดไฟล์ CSV ตามต้องการได้
CanCeylan

ฉันจะมีข้อผิดพลาด "SyntaxError: โทเค็นที่ไม่คาดคิด ILLEGAL" มีบรรทัด "fopen (" php: // output "," w ");" เมื่อฉันเปลี่ยนเป็น "$ fp = fopen ('stats.csv', 'w');" มันไม่แสดงข้อผิดพลาด แต่แน่นอนมันไม่ทำงาน ฉันจะแก้ปัญหาได้อย่างไร
CanCeylan

@CanCeylan นั่นเป็นคำถามในสิทธิของตนเองและฉันต้องการรายละเอียดเพิ่มเติมเพื่อแก้ไข
Xeoncross

1
เพิ่มfputcsv($outstream, array_keys($results[0]));ก่อนที่foreachจะรวมส่วนหัวคอลัมน์
Justin

16

นอกเหนือจากที่กล่าวมาทั้งหมดคุณอาจต้องเพิ่ม:

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

มันมีประโยชน์มากเมื่อจัดการไฟล์ที่มีหลายภาษาเช่นชื่อบุคคลหรือเมือง


9

เธรดเก่าไปหน่อยฉันรู้ แต่สำหรับการอ้างอิงในอนาคตและ noobs เป็นตัวฉันเอง:

ทุกคนที่นี่อธิบายวิธีการสร้าง CSV แต่พลาดส่วนพื้นฐานของคำถาม: วิธีการเชื่อมโยง เพื่อเชื่อมโยงไปยังการดาวน์โหลดไฟล์ CSV คุณเพียงแค่เชื่อมโยงไปยังไฟล์. php ซึ่งจะตอบกลับว่าเป็นไฟล์. csv ส่วนหัวของ PHP ทำเช่นนั้น สิ่งนี้ช่วยให้สิ่งที่น่าสนใจเช่นการเพิ่มตัวแปรในการสืบค้นและปรับแต่งผลลัพธ์:

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

my_csv_creator.php สามารถทำงานกับตัวแปรที่กำหนดในการสืบค้นและตัวอย่างเช่นใช้แบบสอบถามฐานข้อมูลที่แตกต่างกันหรือปรับแต่งเปลี่ยนคอลัมน์ของ CSV ปรับแต่งชื่อไฟล์และอื่น ๆ เช่น:

User_John_Doe_10_Dec_11.csv

1
เอ่อ - ทุกคนที่อ่านข้อความนี้ระวังวิธีการนี้มาก ฉันจะเดิมพันว่าอินพุตไม่ได้รับการหลบหนีอย่างเหมาะสมและอาจนำไปสู่ช่องโหว่ความปลอดภัยขนาดใหญ่ในแอปพลิเคชันของคุณ
calumbrodie

วิธีการของเขาปลอดภัยมากและใช้งานได้ดี คุณสามารถควบคุมการเข้าถึงด้วยเซสชันได้อย่างง่ายดายและคุณยังสามารถเก็บข้อมูลทั้งหมดที่คุณต้องการใส่ลงใน csv ในเซสชัน var จากนั้นเพียงยกเลิกการตั้งค่าเป็นส่วนหนึ่งของกระบวนการแปลงเป็น csv ฉันขอแนะนำให้ใช้ vars เซสชันแทนสตริงการสืบค้น
อนินทรีย์

1
ไม่มีช่องโหว่ด้านความปลอดภัยต่อวิธีการนี้ ตราบใดที่ไฟล์ php ที่อ้างอิงนั้นทำอยู่มันเป็นงานด้านสุขอนามัยและการตรวจสอบการเข้าถึง แต่มันก็ไม่สมเหตุสมผลที่จะแสดงทั้งหมดที่นี่ จุดโพสต์คือคุณสามารถเชื่อมโยงไปยังสิ่งที่ url สร้าง csv
danielson317

8

สร้างไฟล์ของคุณจากนั้นส่งคืนการอ้างอิงไปยังส่วนหัวที่ถูกต้องเพื่อทริกเกอร์บันทึกเป็น - แก้ไขสิ่งต่อไปนี้ตามต้องการ ใส่ข้อมูล 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);

1
การใช้ "inline" Content-Dispositionหมายความว่าเบราว์เซอร์ควรพยายามแสดงโดยไม่ต้องดาวน์โหลด (IE มักจะฝังอินสแตนซ์ของ Excel สำหรับสิ่งนั้น) "ไฟล์แนบ" คือสิ่งที่จำเป็นในการบังคับให้ดาวน์โหลด
Gert van den Berg

5

นี่คือตัวอย่างการทำงานเต็มรูปแบบโดยใช้ 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);
}

4

ขั้นแรกให้สร้างข้อมูลเป็น String โดยใช้เครื่องหมายจุลภาคเป็นตัวคั่น (คั่นด้วย ",") บางสิ่งเช่นนี้

$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

เฮ้มันทำงานได้ดีมาก .... !!!! ขอบคุณ Peter Mortensen และ 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;
}

?>


อย่าไม่ใช้รหัสนี้ในการผลิตก็จะมีความเสี่ยงกับการฉีด SQL
ntzm

2

วิธีง่าย ๆ -

$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 และใหม่กว่าเท่านั้น


2

คุณสามารถเขียนข้อมูลของคุณลงใน 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);

1

วิธีที่ง่ายที่สุดคือใช้คลาส 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'); 

1

แทน:

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

1

วิธีแก้ปัญหาที่ดีมากมาแล้ว ฉันแค่ใส่รหัสทั้งหมดเพื่อที่มือใหม่จะได้รับความช่วยเหลือทั้งหมด

<?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 บนเบราว์เซอร์


0

หากต้องการให้ส่งเป็นไฟล์ CSV และตั้งชื่อไฟล์ให้ใช้ header ():

http://us2.php.net/header

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

สำหรับการสร้าง CSV คุณจะวนซ้ำชุดผลลัพธ์การจัดรูปแบบผลลัพธ์และส่งเช่นเดียวกับที่คุณทำกับเนื้อหาอื่น ๆ


0

การเขียนรหัส CSV ของคุณอาจเสียเวลาเพียงแค่ใช้แพ็คเกจเช่น league / csv - มันเกี่ยวข้องกับสิ่งที่ยากสำหรับคุณเอกสารเป็นสิ่งที่ดีและมีเสถียรภาพ / เชื่อถือได้มาก:

http://csv.thephpleague.com/

คุณจะต้องใช้นักแต่งเพลง หากคุณไม่ทราบว่าฉันเป็นนักแต่งเพลงคนใดขอแนะนำให้คุณดู: 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

จะเขียนไฟล์ CSV โดยใช้สคริปต์ PHP ได้อย่างไร จริงๆแล้วฉันก็กำลังค้นหาเช่นกัน มันเป็นเรื่องง่ายด้วย PHP fputs (ตัวจัดการเนื้อหา) - ฟังก์ชั่นนี้ทำงานได้อย่างมีประสิทธิภาพสำหรับฉัน ก่อนอื่นคุณต้องเปิดไฟล์ที่คุณต้องเขียนเนื้อหาโดยใช้ 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);
}

เป็นที่นิยมเสมอในการเพิ่มรหัสไปที่ตัวเองแทนที่จะเชื่อมโยงเป็นลิงค์มีแนวโน้มที่จะเปลี่ยนแปลงหรือหายไปในช่วงเวลา
Sgoettschkes

คำตอบของคุณคือด้ายเก่ามาก ในขณะที่ในปี 2008 มันเป็นวิธีปฏิบัติมาตรฐานในการสร้างบรรทัดที่คั่นด้วยเครื่องหมายจุลภาคของคุณเองวิธีที่ถูกต้องเนื่องจาก PHP 5.1.0 จะใช้ฟังก์ชัน fputcsv ในตัว ( php.net/fputcsv ) ระวังเมื่ออ่านเธรดเก่าเพื่อให้แน่ใจว่าข้อมูลที่อยู่ในนั้นยังคงเกี่ยวข้อง
ลุคมิลส์

-1

ใส่$outputข้อมูล CSV และ echo ในส่วนหัวด้วยตัวแปรที่ถูกต้อง

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;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.