Загрузка файла при помощи ajax запроса на лету.
Тут пришлось провозиться пол ночи, для решения достаточно типовой задачи. Выдача результат работы скрипта в виде zip файла и отдача его клиенту с последующим удалением. Оказалось, этот случай практически не освящен в мануалах.
Собрал по частям следующее решение
$name_ = $_FILES['fileZip']['name']; $name = urlencode($name_);
var oReq = new XMLHttpRequest(); oReq.open("GET", "<?php echo $_SERVER["REQUEST_URI"]."?file=$name"; ?>", true); oReq.responseType = "arraybuffer"; oReq.onload = function(oEvent) { var blob = new Blob([oReq.response], {type: "application/zip"}); var link = document.createElement('a'); link.setAttribute("type", "hidden"); link.href = window.URL.createObjectURL(blob); link.download = '<?php echo $name_;?>'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; oReq.send();
Серверная часть примерна следующая:
/* * Выдача ZIP файла */ function file_force_download($file) { if (file_exists($file)) { // сбрасываем буфер вывода PHP, чтобы избежать переполнения памяти выделенной под скрипт // если этого не сделать файл будет читаться в память полностью! if (ob_get_level()) { ob_end_clean(); } // заставляем браузер показать окно сохранения файла header('Content-Description: File Transfer'); header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename=' . basename($file)); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($file)); // читаем файл и отправляем его пользователю readfile($file); exit; } }
Функции архивирования
define('DS', DIRECTORY_SEPARATOR); /* * Рекурсивная архивация файлов */ function addFileRecursion($zip, $dir, $start = '') { if (empty($start)) { $start = $dir; } if ($objs = glob($dir . '/*')) { foreach($objs as $obj) { if (is_dir($obj)) { addFileRecursion($zip, $obj, $start); } else { $zip->addFile($obj, str_replace($start . '/', '', $obj)); } } } } /* * Заархивировать директорию */ function archiveDirectory($dir,$zipFileNameWithPath ) { $zip = new ZipArchive(); $zip->open($zipFileNameWithPath, ZipArchive::CREATE|ZipArchive::OVERWRITE); addFileRecursion($zip, $dir); $zip->close(); }
Ну и операции с файлом:
// если есть запрос на отдачу файла if(isset($_GET['file']) && $_GET['file']) { // определяем имя $filename = urldecode($_GET['file']); // прибавляем к нему адрес временной папки $tmpfname = sys_get_temp_dir().DS.$filename; // архивируем временную папку archiveDirectory(__DIR__.DS.'tmp',$tmpfname); // Отдаем файл file_force_download($tmpfname); // завершаем скрипт (Машу каслом не испортишь) exit(); }