Pregunta

Estoy tratando de usar el siguiente código para crear un archivo zip desde un directorio y servirlo al usuario a través de una descarga 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);

Puedo crear el archivo zip, pero descargarlo a través de http no funciona. Si descargo el archivo zip creado con un cliente ftp, Mac's Stuffit Expander descomprime los archivos perfectamente, pero si lo descargo a través de http, el descomprimidor mac crea un bucle sin fin. Lo que quiero decir con esto es que el archivo que descargo se llama course.zip, luego descomprimir el archivo da course.zip.cpgz y descomprimir ese archivo da course.zip nuevamente ... y así sucesivamente.

¿Alguien tiene alguna idea?

¡Gracias!

¿Fue útil?

Solución

  1. Volver a comprimirlo cada vez que se solicita no es una buena idea. Intente hacerlo solo si el archivo ZIP aún no existe.

  2. Si es un archivo volátil o simplemente un archivo pequeño que desea transferir comprimido, intente usar ob_start ('ob_gzhandler') , más simple, más pequeño, más limpio. El archivo se transfiere comprimido, pero el lado del cliente lo guarda en su formato original.

  3. Es necesario especificar el encabezado Content-Length para permitir que el descargador conozca el final del archivo, permitiendo el control del progreso, la detección de corrupción del archivo y evitando el bloqueo de la sesión HTTP (si Connection está en Keep -Modo vivo), tal vez la falta de este encabezado sea la raíz del problema.

Otros consejos

Tuve este problema y resultó que el archivo zip descargado tenía una nueva línea insertada al principio.

Resuelto mediante el uso de funciones ob_clean y 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");

Como lo sugiere karim79 , pondré mi comentario como respuesta: ¿qué sucede si cambia el tipo MIME? desde application / octet-stream a application / zip?

Además, veo que está utilizando un programa zip de línea de comando, pero no verifica el éxito del zip, y tampoco verifica si el archivo existe antes de intentar enviarlo al navegador de los usuarios finales . Intente codificar un nombre de archivo, utilizando manualmente zip para garantizar un archivo zip correctamente formado, y luego vea si su código lo escupe correctamente en su navegador.

Lo que está viendo es que la utilidad de archivo no reconoce el archivo zip como un archivo zip e intentó comprimir el archivo zip. La segunda operación simplemente descomprime el primer archivo creado, por lo que nunca abre realmente el archivo. Esto se debe a que el zip está dañado.

Es posible que el navegador de alguna manera haya dañado el archivo zip (¿conversiones de nueva línea a alguien?) durante el proceso de descarga. Como se mencionó, verifique el tipo mime y use el encabezado php () para establecer el tipo MIME correcto (aplicación / zip).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top