for - PHP ZipArchive corrupto en Windows
php for windows xp (13)
Estoy usando la clase ZipArchive de PHP para crear un archivo zip que contenga fotos y luego lo sirvo en el navegador para descargarlo. Aquí está mi código:
/**
* Grabs the order, packages the files, and serves them up for download.
*
* @param string $intEntryID
* @return void
* @author Jesse Bunch
*/
public static function download_order_by_entry_id($intUniqueID) {
$objCustomer = PhotoCustomer::get_customer_by_unique_id($intUniqueID);
if ($objCustomer):
if (!class_exists(''ZipArchive'')):
trigger_error(''ZipArchive Class does not exist'', E_USER_ERROR);
endif;
$objZip = new ZipArchive();
$strZipFilename = sprintf(''%s/application/tmp/%s-%s.zip'', $_SERVER[''DOCUMENT_ROOT''], $objCustomer->getEntryID(), time());
if ($objZip->open($strZipFilename, ZIPARCHIVE::CREATE) !== TRUE):
trigger_error(''Unable to create zip archive'', E_USER_ERROR);
endif;
foreach($objCustomer->arrPhotosRequested as $objPhoto):
$filename = PhotoCart::replace_ee_file_dir_in_string($objPhoto->strHighRes);
$objZip->addFile($filename,sprintf(''/press_photos/%s-%s'', $objPhoto->getEntryID(), basename($filename)));
endforeach;
$objZip->close();
header(''Last-Modified: ''.gmdate(''D, d M Y H:i:s'', filemtime($strZipFilename)).'' GMT'', TRUE, 200);
header(''Cache-Control: no-cache'', TRUE);
header(''Pragma: Public'', TRUE);
header(''Expires: '' . gmdate(''D, d M Y H:i:s'', time()) . '' GMT'', TRUE);
header(''Content-Length: ''.filesize($strZipFilename), TRUE);
header(''Content-disposition: attachment; filename=press_photos.zip'', TRUE);
header(''Content-Type: application/octet-stream'', TRUE);
ob_start();
readfile($strZipFilename);
ob_end_flush();
exit;
else:
trigger_error(''Invalid Customer'', E_USER_ERROR);
endif;
}
Este código funciona realmente bien con todos los navegadores excepto IE. En IE, el archivo se descarga correctamente, pero el archivo zip está vacío. Al intentar extraer los archivos, Windows me dice que el archivo zip está dañado. Alguien ha tenido este problema antes?
Editar actualización: Después de la sugerencia de @profitphp, cambié mis encabezados a esto:
header("Cache-Control: public");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
//header("Content-Description: File Transfer");
//header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=/"pressphotos.zip/"");
//header("Content-Transfer-Encoding: binary");
header("Content-length: " . filesize($strZipFilename));
Además, aquí hay una captura de pantalla del error en Windows después de abrir con Firefox:
Este error se produce tanto en IE como en Firefox en Windows. Funciona bien en Mac. Además, en Windows, el tamaño del archivo parece ser correcto:
Editar # 2 Este problema está sembrado. Vea mi respuesta a continuación.
Además de lo que otros sugirieron, es importante prestar atención a los nombres de sus archivos y directorios, ya que a Windows no necesariamente le gustan los nombres y las rutas de Linux. A veces también se les escapa de manera diferente cuando se cierran. Los ejemplos son numerosos, pero lo más importante
- * archivos de puntos (. y ...), archivos con solo diferencias de caso (nombre.txt y NOMBRE.txt),
- rutas de archivos absolutas (/tmp/file.txt )*.
- Algunos otros caracteres permitidos en los nombres de archivos en Windows podrían causar problemas cuando se utiliza el Explorador de Windows para abrir archivos. En mi caso, el personaje fue el factor decisivo, pero tomó mucho trabajo para averiguarlo.
Así que antes de continuar usando muchos parámetros a través de exec (''zip ...''), sugiero seguir un procedimiento simple:
- Localice la carpeta o archivo de su sitio web con cremallera.
- ejecute: zip -9 -r -k zip-modified-names.zip / ruta / a / su / carpeta
- Presta atención a lo que escupe la consola. En mi caso '':'' en los nombres de archivo fueron eliminados.
- Mueva el archivo zip a una máquina con Windows e intente abrirlo.
Si esto funciona, es mejor que elimines los caracteres que han sido eliminados por la opción -k de tus archivos / directorios. Intenta comprimir normalmente. Tenga en cuenta que algunos parámetros como -k tienen efectos secundarios. En este caso, -k contradice con la opción -q (para enlaces sym).
También la opción -k puede hacer que sus nombres de archivo sean ilegibles. En mi caso, mis archivos fueron nombrados según el tiempo de creación (por ejemplo, 10: 55: 39.pdf) para facilitar la localización del registro requerido de los archivos, pero la opción -k lo convirtió en 105539.pdf que no es fácil de leer para los usuarios. Por lo tanto, cambié los nombres a 10_55_39.pdf, que se abre en Windows sin usar la opción -k pero aún se puede leer.
Además de esto, el uso de PCLZip le facilitaría mucho la vida, ya que puede agregar una carpeta completa a la vez y también modificar la ruta de acceso de los archivos en una sola línea. En mi caso, elimino / tmp / directory / de mis archivos zip con los parámetros segundo y tercero que evitan otro problema de compatibilidad de Windows (que tiene una ruta absoluta en los archivos zip):
$v_list = $zip->create( $sourceFolder, PCLZIP_OPT_REMOVE_PATH, $sourceFolder . DIRECTORY_SEPARATOR);
if ($v_list == 0) {
throw new /Exception($zip->errorInfo(true));
}
Cambia tu código:
header(''Content-Length: ''.filesize($strZipFilename), TRUE);
Con:
header(''Content-Length: ''.file_get_contents($strZipFilename));
El uso de caracteres especiales, como el subrayado, causa problemas porque ZipArchive requiere nombres de entrada codificados en IBM850. Vea los comentarios en el manual de PHP en línea: http://www.php.net/manual/en/function.ziparchive-addfile.php#95725 .
Estaba usando la marca de tiempo en el nombre del archivo zip. En realidad, el sistema de archivos de Windows no admite caracteres especiales como ": / / *? <> |"
Después de eliminar ":" de la parte de tiempo, funciona como un amuleto.
He estado teniendo este problema durante una hora. Después de probar 10 soluciones diferentes, lo resolví asegurándome de que el script existe después de generar el archivo ZIP:
readfile($zip_name);
unlink($zip_name);
**exit();**
He tenido problemas con esto antes. Intenta quitar el encabezado de tipo de contenido. Aquí está el código que se me ocurrió para que funcionara en IE y FF. Observe las líneas comentadas, estaba teniendo los mismos problemas con diferentes combos de los que están en.
header("Cache-Control: public");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
//header("Content-Description: File Transfer");
//header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=/"adwords-csv.zip/"");
//header("Content-Transfer-Encoding: binary");
header("Content-length: " . filesize($filename));
Ok, después de mucho conflicto, me di cuenta del problema. El problema viene de la siguiente línea de código:
$objZip->addFile($filename,sprintf(''/press_photos/%s-%s'', $objPhoto->getEntryID(), basename($filename)));
Por alguna razón, la /press_photos/
parte de esa ruta para el nombre del archivo local (interno) dentro del archivo zip estaba causando que Windows pensara que el archivo zip estaba dañado. Después de modificar la línea para que se vea como está debajo, Windows abrió los archivos zip correctamente. Uf.
$objZip->addFile($filename,sprintf(''%s-%s'', $objPhoto->getEntryID(), basename($filename)));
Recientemente tuve un problema similar al que describiste. Encontré que ZipArchive es inestable en el mejor de los casos.
Resolví mis problemas con esta sencilla biblioteca.
http://www.phpconcept.net/pclzip
include_once(''libs/pclzip.lib.php'');
...
function zip($source, $destination){
$zipfile = new PclZip($destination);
$v_list = $zipfile->create($source, '''', $source); }
$ source = carpeta que quería comprimir $ destination = ubicación del archivo zip
Pasé 2 días buscando ZipArchive y luego resolví todos los problemas con PCLZip en 5 minutos.
Espero que esto le ayude a usted y a cualquier otra persona que tenga este problema (ya que está cerca del principal resultado de Google sobre el problema).
Solo en caso de que alguien más esté golpeando su pared contra un muro de ladrillo durante unas horas y sufra como yo lo hice. Tuve el mismo problema, y ninguna de las soluciones ayudó, hasta que me di cuenta de que cargué algunas bibliotecas en mi PHP y una de ellas tenía una línea vacía después del código?>. Al llamar a la biblioteca con include(/path/to/lib/lib.php);
se envió una línea vacía al navegador, lo que provocó que el código postal se clasificara como dañado por Windows. (Winzip, Total Commander, etc. no tuvo problemas con eso). Así que asegúrese de que no haya una biblioteca importada o, si la hay, que no tenga espacios ni líneas vacías ...
Todas estas sugerencias pueden ayudarlo, pero en mi caso necesito escribir un ob_clean (); antes del primer encabezado (''''); porque algún archivo que incluyo antes imprime algunos caracteres que rompieron el archivo zip en Windows.
$zip=new ZipArchive();
$zip->open($filename, ZIPARCHIVE::CREATE);
$zip->addFile($file_to_attach,$real_file_name_to_attach);
$zip->close();
ob_clean();
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header(''Content-Type: application/x-download'');
header(''Content-Disposition: attachment; filename="file.zip"'');
readfile($filename);
exit;
Tuve este mismo problema, y mi solución fue similar a la respuesta correcta en este hilo. Cuando coloca un archivo en el archivo, no puede tener archivos absolutos (archivos que comienzan con una barra oblicua) o no se abrirá en Windows por algún motivo.
Así que funcionó no porque él (Jesse Bunch, la respuesta seleccionada en el momento de escribir esto) eliminó la carpeta que lo contenía, sino porque eliminó la barra inicial.
Arreglé el problema cambiando
$zip->addFile($file, $file); // $file is something like /path/to/file.png
a
// we make file relative by removing beginning slash so it will open in Windows
$zip->addFile($file, ltrim($file, ''/''));
y luego fue capaz de abrir en Windows!
Esa es probablemente la misma razón por la que funciona pclzip (la respuesta de Plahcinski). Apuesto a que automáticamente se quita la barra inicial.
No hubiera descubierto esto sin un comentario particular en la página de documentación de PHP ZipArchive::addFile
.
Yo tuve el mismo problema. Este código funcionó para mí, ¡pero TENÍA QUE PONER EN LA PRIMERA LÍNEA en mi archivo php! Si puse el código en medio del archivo, no funcionó. Tal vez algunos problemas de codificación?
// Prepare File
$file = tempnam("tmp", "zip");
$zip = new ZipArchive();
$zip->open($file, ZipArchive::OVERWRITE);
// Staff with content
$zip->addFile($filepathOnServer, ''mypic.jpg'');
// Close and send to users
$zip->close();
header(''Content-Type: application/zip'');
header(''Content-Disposition: attachment; filename="filename.zip"'');
readfile($file);
unlink($file);
ob_clean(); //very important
// http headers for zip downloads
header("Pragma: public");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Cache-Control: public");
header(''Content-Type: application/x-download'');
header("Content-Disposition: attachment; filename=/"filename.zip/"");
header("Content-Length: ".filesize($filepath ));
@readfile($filepath );
unlink($filepath); //very important
exit;//very important
Esto funcionó para mí mientras intentaba las soluciones anteriores.