Làm cách nào để tạo và tải xuống tệp csv từ tập lệnh php?


89

Tôi là một lập trình viên mới vào nghề và tôi đã tìm kiếm rất nhiều về câu hỏi của mình nhưng không thể tìm thấy giải pháp hoặc hướng dẫn hữu ích về điều này.

Mục tiêu của tôi là tôi có một mảng PHP và các phần tử của mảng đang hiển thị trong một danh sách trên trang.

Tôi muốn thêm một tùy chọn để nếu người dùng muốn, họ có thể tạo tệp CSV với các phần tử mảng và tải xuống.

Tôi không biết làm thế nào để làm điều này. Tôi cũng đã tìm kiếm rất nhiều. Nhưng vẫn chưa tìm thấy bất kỳ nguồn hữu ích nào.

Vui lòng cung cấp cho tôi một số hướng dẫn hoặc giải pháp hoặc lời khuyên để tôi tự thực hiện nó. Vì tôi là người mới, vui lòng cung cấp các giải pháp dễ thực hiện.

Mảng của tôi trông giống như:

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 cho một tập tin CSV là một chút quá nhiều .. php.net/manual/en/function.fputcsv.php
Damien Pirsy

Hiển thị cấu trúc mảng của bạn và tôi c một cung cấp một số mã để biến các yếu tố vào một csv
nửa nhanh

@ nửa nhanh Tôi đã thêm các cấu trúc mảng trong bài
user2302780

2
làm thế nào có thể thêm tiêu đề cột trong tệp csv?
user2302780

bản sao có thể có của Xuất sang CSV qua PHP
Michal Mau

Câu trả lời:


200

Bạn có thể sử dụng fputcsv () tích hợp sẵn cho mảng của mình để tạo các dòng csv chính xác từ mảng của bạn, vì vậy bạn sẽ phải lặp lại và thu thập các dòng, như sau:

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

Để làm cho trình duyệt cung cấp hộp thoại "Lưu dưới dạng", bạn sẽ phải gửi tiêu đề HTTP như thế này (xem thêm về tiêu đề này trong rfc ):

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

Để tất cả chúng cùng nhau:

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

Và bạn có thể sử dụng nó như thế này:

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

Cập nhật:
Thay vì php://memorybạn cũng có thể sử dụng php://outputcho trình mô tả tệp và loại bỏ việc tìm kiếm và như vậy:

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
tại sao không phải echocác dòng CSV được tạo trực tiếp trong vòng lặp?
Alex Shesterov

1
@AlexShesterov, lý do chính là fputcsv()không trả về dòng đã tạo, nó sẽ cần một bộ mô tả tệp để ghi vào. Bạn có thể tua lại, ghi, xóa bộ đệm trên mỗi lần lặp lại mặc dù nếu bạn bị hạn chế về bộ nhớ. Hoặc chỉ sử dụng một tệp tạm thời thực sự thay thế.
complex857,

@ complex857 làm cách nào để thêm tiêu đề cột cho csv?
user2302780

@ user2302780: Bạn chỉ cần thêm tiền tố cho dữ liệu của mình bằng một hàng tên cột. Bạn có thể sử dụng các phím từ dữ liệu mảng với một cái gì đó giống như$data = array_merge(array(array_keys($data[0])), $data);
complex857

1
@JoseRojas được mong đợi vì một khi bạn đặt một cái gì đó qua dây (rằng những gì xuất ra những thứ bằng php có nghĩa là về mặt khái niệm) bạn không thể quay lại điều đó. Để sử dụng, php://outputhãy xem mẫu mã cập nhật thứ hai.
complex857,

18

Tôi không có đủ danh tiếng để trả lời giải pháp @ complex857. Nó hoạt động tuyệt vời, nhưng tôi phải thêm; ở cuối tiêu đề Nội dung-Bố trí. Nếu không có nó, trình duyệt sẽ thêm hai dấu gạch ngang ở cuối tên tệp (ví dụ: thay vì "export.csv", tệp sẽ được lưu dưới dạng "export.csv--"). Có thể là nó cố làm sạch \ r \ n ở cuối dòng tiêu đề.

Dòng đúng sẽ như thế này:

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

Trong trường hợp CSV có các ký tự UTF-8, bạn phải thay đổi mã hóa thành UTF-8 bằng cách thay đổi dòng Content-Type:

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

Ngoài ra, tôi thấy sử dụng rewind () thay vì fseek ():

rewind($f);

Cảm ơn giải pháp của bạn!


2
Tôi chưa bao giờ trải qua --ở phần cuối của tên tập tin bản thân mình, tuy nhiên tôi đã cập nhật các câu trả lời (tại sao không chỉ cần đưa ra một chỉnh sửa?)
complex857

14

Hãy thử ... tải xuống 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();
?>

sẽ bị hỏng nếu giá trị trường chứa, đó là lý do tại sao tôi thích tsv hơn (tab hiếm hơn và chúng tôi có thể thay thế nó hoặc thứ gì đó)
oriadam

14

Đó là chức năng mà tôi đã sử dụng cho dự án của mình và nó hoạt động như mong đợi.

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
Tôi đã gặp khó khăn khi cố gắng triển khai nó trong hook send_headers của wordpress, vì mỗi lần nó thêm tất cả html của trang hiện tại vào cuối tệp csv. Những câu trả lời này giúp ích cho tôi rất nhiều, nhưng tôi sử dụng nó mà không có hoạt động đệm.
Oleg Apanovich

bộ đệm đầu ra sạch đã giải quyết cho tôi vấn đề mà trước khi sử dụng các hàng mã này ở đầu và cuối tệp được hình thành là các hàng trống.
Sharunas Bielskis

8

Sử dụng mã dưới đây để chuyển đổi mảng php thành 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

Nếu cấu trúc mảng của bạn sẽ luôn đa chiều theo kiểu chính xác đó, thì chúng ta có thể lặp lại qua các phần tử như sau:

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

Đó là một cách để làm điều đó ... bạn có thể làm thủ công nhưng cách này nhanh hơn và dễ hiểu và dễ đọc hơn.

Sau đó, bạn sẽ quản lý tiêu đề của mình một cái gì đó mà complex857 đang làm để lấy ra tệp. Sau đó, bạn có thể xóa tệp bằng cách sử dụng unlink () nếu bạn không cần nó nữa hoặc bạn có thể để nó trên máy chủ nếu bạn muốn.


-2

Sử dụng những điều sau đây,

echo "<script type='text/javascript'> window.location.href = '$file_name'; </script>";
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.