16

I have a requirement to create 3 CSV files (in memory) during a single HTTP request, ZIP the files into a single compressed file and return the compressed file as a HTTP response.

I have the following code to create the zip file...

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

However, I don't know how to create the CSV files in memory.

How can I achieve this?

1
  • Ha! We're working on exactly the same project. … Fred? Commented Dec 20, 2022 at 18:46

2 Answers 2

28

Try this...

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

I've just tested this on my machine and it works fine.

I used this link as a reference, It may be useful.

MetaShock Reference

Sign up to request clarification or add additional context in comments.

Comments

0

You can use php's memory wrapper:

$zipname = 'php://memory';

On systems having /dev/shm filesystem you can create files there, they will be kept only in memory and only accessible to current process. Don't forget to remove them after sending, web server process will keep running.

2 Comments

Will this support multiple files? For instance...$zipname1 = 'php://memory';$zipname2 = 'php://memory'; $zipname3 = 'php://memory';
Each fopen('php://memory', $mode) will open separate in moemory file. The problem is they are not named, closing the file pointer will loose what was written. I don't know ZipArchive library to know if this is a problem, likely you should not call $zip->close() but something else to get the stream. There's yet another solution, I'll update my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.