Estoy intentando enviar un zip generado por un servidor php cuando lo solicite el $ .ajax de jquery.
Este es mi código:
php:
$file = tempnam($a_folder_path, "zip"); $zip = new ZipArchive(); $zip->open($file, ZipArchive::OVERWRITE); $zip->addFile($path_to_json, 'data.json'); $zip->close(); rename($file, $file . '.zip'); $filename = basename($file . '.zip'); $filepath = $file . '.zip'; while (ob_get_level()) { ob_end_clean(); } header("Pragma: public"); header("Expires: 0"); header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0"); header("Content-Description: File Transfer"); header("Content-type: application/octet-stream"); header("Content-Disposition: attachment; filename=\"".$filename."\""); header("Content-Transfer-Encoding: binary"); header("Content-Length: ".filesize($filepath)); ob_end_flush(); echo file_get_contents($filepath); //@readfile($filepath);
$.ajax( { url: myUrl, type: 'POST', data: { "leData" : "some_data" }, context: document.body, cache: false, success: function(data) { console.log(data); console.log(data.length); var bytes = new Uint8Array(data.length); for (var i=0; i<data.length; i++) { bytes[i] = data.charCodeAt(i); } blob = new Blob([bytes], {type: "application/zip"}) saveAs(blob, "test.zip");//trying to access data with FileSave.js zip.load(data);//trying to access data with JSZip.js jsonData = JSON.parse(zip.file('shouldBeThere.json').asText()); }, error: function() { alert('error'); } } );
Lo que pasa:
El problema es que no tengo idea si el problema viene de PHP o de JavaScript. No sé si PHP está enviando un archivo zip dañado o si JavaScript no lo está leyendo correctamente.
He probado todas las combinaciones de encabezados de php y los métodos que he encontrado en internet. También he intentado hacer cosas de manera diferente en javascript: usando un ArrayBuffer en lugar de Uint8Array, pasando bytes en lugar de datos a zip.load (), usando {type: “application / octet-stream”} en Blob ().
Finalmente encontré una solución: se debe especificar para ajax el tipo de datos recibidos y luego convertir estos datos Unicode en caracteres. Aquí está mi nuevo código javascript:
$.ajax( { url: myUrl, type: 'POST', data: { "leData" : "some_data" }, context: document.body, cache: false, dataType: 'text', //solution code mimeType: 'text/plain; charset=x-user-defined', //solution code success: function(data) { console.log(data); console.log(data.length); newContent = ""; //solution code for (var i = 0; i < data.length; i++) { //solution code newContent += String.fromCharCode(data.charCodeAt(i) & 0xFF); //solution code } var bytes = new Uint8Array(newContent.length); //modified for (var i=0; i
Mi código php estaba bien, incluso funcionaba sin encabezados. Aquí está el código php mínimo que necesito:
$file = tempnam($a_folder_path, "zip"); $zip = new ZipArchive(); $zip->open($file, ZipArchive::OVERWRITE); $zip->addFile($path_to_json, 'data.json'); $zip->close(); rename($file, $file . '.zip'); echo file_get_contents($file . '.zip');
Solución inspirada en este
Estaba buscando una solución para el siguiente problema: “Enviar una solicitud en phl url para crear un archivo zip de un directorio y descargarlo utilizando la respuesta ajax”.
El siguiente código funciona:
PHP parte para zip:
// Function for creating a zip of a directory function zipFilesAndDownload($directory, $file_names) { $zip = new ZipArchive(); if ($zip->open("../temp/$directory.zip", ZIPARCHIVE::CREATE) !== TRUE) { exit("Error on creating '../temp/$directory.zip'"); } foreach ($file_names as $file) { $zip->addFile($file, substr($file, strrpos($file, "/") + 1)); } $zip->close(); readfile("../temp/$directory.zip"); unlink("../temp/$directory.zip"); } // Code for creating array of filenames $directory = $_POST['directory']; // eg a directory with ID "123" $dirToZip = "../uploaddir/$directory"; if ($handle = opendir($dirToZip)) { $file_names = array(); while (($file = readdir($handle)) !== false) { if ($file != "." && $file != "..") { array_push($file_names, "$dirToZip/$file"); } } closedir($handle); zipFilesAndDownload($directory, $file_names); }
JS parte:
$(document).on('click', '#downloadDirectory', function () { var directory = '123'; $.ajax({ type: 'POST', url: '../createZip.php', data: {"directory": directory}, dataType: 'text', mimeType: 'text/plain; charset=x-user-defined', success: function (data) { var bytes = new Uint8Array(data.length); for (var i = 0; i < data.length; i++) { bytes[i] = data.charCodeAt(i); } blob = new Blob([bytes], {type: "application/zip"}) saveAs(blob, "pictures.zip"); // "saveAs" function is provided in FileSaver.js } }); });