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