Domanda

Sto cercando di utilizzare il seguente codice per creare un file zip da una directory e servirlo all'utente tramite un download http:

 // write the file
file_put_contents($path . "/index.html", $output);

// zip up the contents
chdir($path);
exec("zip -r {$course->name} ./");

$filename = "{$course->name}.zip";

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' .urlencode($filename));
header('Content-Transfer-Encoding: binary');

readfile($filename);

Sono in grado di creare il file zip, ma il download su http non funziona. Se scarico il file zip creato utilizzando un client ftp, Stuffit Expander di Mac decomprime i file correttamente, ma se lo scarico su http, il decompressore di mac crea un ciclo infinito. Quello che intendo con questo è dire che il file che scarico si chiama course.zip, quindi decomprimendo il file dà course.zip.cpgz e decomprimendo quel file dà course.zip di nuovo ... e ancora e ancora.

Qualcuno ha qualche idea?

Grazie!

È stato utile?

Soluzione

  1. Ri-zipparlo ogni volta che viene richiesto non è una buona idea. Prova a farlo solo se il file ZIP non esiste già.

  2. Se si tratta di un file volatile o di un singolo file di piccole dimensioni che si desidera trasferire compressi, provare invece a utilizzare ob_start ('ob_gzhandler') , più semplice, più piccolo, più pulito. Il file viene trasferito compresso, ma viene salvato nel suo formato originale dal lato client.

  3. È necessario specificare l'intestazione Content-Length per consentire al downloader di conoscere la fine del file, consentendo il controllo dell'avanzamento, il rilevamento del danneggiamento del file ed evitando il blocco della sessione HTTP (se Connection è in Keep -Modalità attiva), forse la mancanza di questa intestazione è la radice del problema.

Altri suggerimenti

Ho riscontrato questo problema e si è scoperto che il file zip scaricato aveva una nuova riga inserita all'inizio.

Risolto usando le funzioni ob_clean e flush

    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false);
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=".basename($archive_file_name));
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize($archive_file_name));
    ob_clean();
    flush();
    echo readfile("$archive_file_name");

Come suggerito da karim79 , inserirò il mio commento come risposta: cosa succede se si cambia il tipo MIME da application / octet-stream a application / zip?

Inoltre, vedo che stai utilizzando un programma zip da riga di comando, ma non controlli la riuscita dello zip e non controlli nemmeno se il file esiste prima di provare a inviarlo al browser degli utenti finali . Prova a codificare a fondo il nome di un file, usando manualmente zip per garantire un file zip correttamente formato, quindi vedi se il tuo codice lo sputerà correttamente nel tuo browser.

Quello che vedi è che l'utilità di archiviazione non riconosce il file zip come file zip e ha provato a comprimere l'archivio zip stesso. La seconda operazione decomprime semplicemente il primo file creato, quindi non si apre mai il file. Ciò è dovuto al danneggiamento dello zip.

È possibile che il browser abbia in qualche modo alterato il file zip (conversioni di newline?) durante il processo di download. Come accennato, controlla il tipo mime e usa l'intestazione php () per impostare il tipo MIME corretto (application / zip).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top