82 lines
2.3 KiB
PHP
82 lines
2.3 KiB
PHP
<?php
|
|
namespace nur\b\io;
|
|
|
|
use nur\file;
|
|
use ZipArchive;
|
|
|
|
/**
|
|
* Class ZipStreamer: classe outil pour faciliter la construction dynamique d'un
|
|
* fichier zip qui est streamé vers l'utilisateur
|
|
*/
|
|
class ZipBuilder {
|
|
const TMPDIR = null;
|
|
|
|
function __construct(string $filename) {
|
|
$tmpzip = file::temp("zipf", static::TMPDIR);
|
|
$zip = new ZipArchive();
|
|
if ($zip->open($tmpzip, ZipArchive::CREATE) !== true) {
|
|
throw new IOException("unable to create $tmpzip");
|
|
}
|
|
$this->filename = $filename;
|
|
$this->tmpzip = $tmpzip;
|
|
$this->zip = $zip;
|
|
$this->deletes = [$tmpzip];
|
|
}
|
|
|
|
private $filename;
|
|
private $tmpzip;
|
|
private $zip;
|
|
private $deletes;
|
|
|
|
/**
|
|
* ajouter une entrée dans le fichier zip avec le nom spécifié
|
|
*
|
|
* un fichier temporaire est préparé, et une instance permettant d'y écrire
|
|
* est retournée. c'est ce fichier qui sera inséré dans le fichier zip.
|
|
*/
|
|
function newFile(string $entryname): IWriter {
|
|
$tmpfile = file::temp("zipe", static::TMPDIR);
|
|
$this->deletes[] = $tmpfile;
|
|
$outw = new FileWriter($tmpfile, "wb");
|
|
if ($this->zip->addFile($tmpfile, $entryname) !== true) {
|
|
$outw->close();
|
|
throw new IOException("unable to add $entryname");
|
|
}
|
|
return $outw;
|
|
}
|
|
|
|
/**
|
|
* ajouter une entrée dans le fichier zip construite à partir du fichier
|
|
* spécifié. ce fichier doit exister jusqu'à ce que la méthode {@link send()}
|
|
* soit appelée
|
|
*/
|
|
function addFile(string $file, ?string $entryname=null): void {
|
|
if ($entryname === null) $entryname = basename($file);
|
|
if ($this->zip->addFile($file, $entryname) !== true) {
|
|
throw new IOException("unable to add $file");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ajouter une entrée dans le fichier zip construite à partir de la chaine
|
|
* spécifiée
|
|
*/
|
|
function addString(string $entryname, string $content): void {
|
|
if ($this->zip->addFromString($entryname, $content) !== true) {
|
|
throw new IOException("unable to add $entryname");
|
|
}
|
|
}
|
|
|
|
/** finaliser le fichier zip et le streamer vers le client */
|
|
function send(): void {
|
|
$this->zip->close();
|
|
$zipf = file::open($this->tmpzip, "rb");
|
|
foreach ($this->deletes as $delete) {
|
|
unlink($delete);
|
|
}
|
|
header("Content-Type: application/zip");
|
|
header("Content-Disposition: attachment; filename=\"$this->filename\"");
|
|
fpassthru($zipf);
|
|
}
|
|
}
|