在内存中创建多个CSV文件并压缩(PHP)

16

我有一个需求,在单个HTTP请求期间创建3个CSV文件(在内存中),将这些文件压缩成一个单独的压缩文件,并将压缩文件作为HTTP响应返回。

我有以下代码来创建zip文件...

$files = array($file1, $file2);
$zipname = 'file.zip';
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
foreach ($files as $file) {
    $zip->addFile($file);
}
$zip->close();

header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);

然而,我不知道如何在内存中创建CSV文件。

我该怎么做呢?


哈!我们正在做完全相同的项目。...弗雷德? - Parapluie
2个回答

28

试试这个...

// some data to be used in the csv files
$headers = array('id', 'name', 'age', 'species');
$records = array(
    array('1', 'gise', '4', 'cat'),
    array('2', 'hek2mgl', '36', 'human')
);

// create your zip file
$zipname = 'file.zip';
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);

// loop to create 3 csv files
for ($i = 0; $i < 3; $i++) {

    // create a temporary file
    $fd = fopen('php://temp/maxmemory:1048576', 'w');
    if (false === $fd) {
        die('Failed to create temporary file');
    }
    
    // write the data to csv
    fputcsv($fd, $headers);
    foreach($records as $record) {
        fputcsv($fd, $record);
    }

    // return to the start of the stream
    rewind($fd);
     
    // add the in-memory file to the archive, giving a name
    $zip->addFromString('file-'.$i.'.csv', stream_get_contents($fd) );
    //close the file
    fclose($fd);
}
// close the archive
$zip->close();


header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);

// remove the zip archive
// you could also use the temp file method above for this.
unlink($zipname);

我刚在我的机器上测试过,它可以正常工作。

我使用了这个链接作为参考,它可能会有用。

MetaShock 参考


非常有帮助。非常感谢。 - Cloud

0
你可以使用 PHP 的 内存包装器
$zipname = 'php://memory';

在具有/dev/shm文件系统的系统上,您可以在那里创建文件,它们将仅保留在内存中,并且仅对当前进程可访问。发送后不要忘记删除它们,Web服务器进程将继续运行。

这个支持多个文件吗?例如... $zipname1 = 'php://memory'; $zipname2 = 'php://memory'; $zipname3 = 'php://memory'; - fml
每个 fopen('php://memory', $mode) 将打开一个单独的内存文件。问题是它们没有命名,关闭文件指针将丢失已写入的内容。我不知道 ZipArchive 库是否存在这个问题,可能你不应该调用 $zip->close() 而是使用其他方法来获取流。还有另一种解决方案,我会更新我的答案。 - Marek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接