把 CSV 数据作为文件下载

If you ever need to save a set of columnar data as a csv file on the server, doing so using fopen() and fputcsv() is pretty simple. What you may not know, and what I didn't know until recently, was how to take that same data and return it as a downloadable csv file (not saved on the server). Turns out, accomplishing this task in Drupal is just as easy as saving a file but with one minor tweak.

Saving To a File

As a recap for some, and a primer for others, here's how we'd take some data and save it as a file on the server:

// Let's get the 50 most recently created published nodes.
$nodes = db_query('SELECT nid, title FROM {node} WHERE status = 1 ORDER BY created DESC LIMIT 50');

// Open the file for writing.
$fh = fopen('nodes.csv', 'w');
// Add a header row
fputcsv($fh, array(t('NID'), t('Title'));

// Loop through our nodes and write the csv data.
foreach($nodes as $node) {
fputcsv($fh, array($node->nid, $node->title));
}

// Close & save the file.
fclose($fh);

This code queries for a set of data, then opens a csv file and writes the values to it. Pretty simple stuff. But what if you want to present this to the browser as a file download, instead of saving to the server?

Saving as a File Download

Fortunately, we only need to change a few lines:


// Let's get the 50 most recently created published nodes.
$nodes = db_query('SELECT nid, title FROM {node} WHERE status = 1 ORDER BY created DESC LIMIT 50');

// Add the headers needed to let the browser know this is a csv file download.
drupal_add_http_header('Content-Type', 'text/csv; utf-8');
drupal_add_http_header('Content-Disposition', 'attachment; filename = nodes.csv');

// Instead of writing to a file, we write to the output stream.
$fh = fopen('php://output', 'w');

// Add a header row
fputcsv($fh, array(t('NID'), t('Title'));

// Loop through our nodes and write the csv data.
foreach($nodes as $node) {
fputcsv($fh, array($node->nid, $node->title));
}

// Close the output stream.
fclose($fh);

In case you didn't catch that, first we needed to add some headers to let the browser know that we're sending a file download. Then, instead of opening a file to write to, we write to php's output stream. Now, when a user clicks a link, or enters the url to a page with this code, they will be prompted to save a file with the data formatted as csv.

Although simple, this was something I'd never had to do before so I thought I'd share this in case others hadn't either.

标签: