Загрузка файла при помощи 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();
}