JavaScript: Еще один вариант загрузки файла по клику на кнопку
Общая идея следующая: по клику на кнопку вызываем AJAX запрос на сервер с определенными параметрами передаваемыми в POST, затем получив в результат запроса файл — формируем в DOM на файл в формате blob, и тут-же её нажимаем. В результате браузер показывает диалоговое окно сохранения файла.
Таким необычным способом мы убиваем несколько зайцев сразу:
- Получаем возможность показать ошибку, если вдруг файл на сервере сформировать не удалось. Это полезно если например файл формируется на сервере «на лету» — например файл XLSX с отчётом
- Мы можем передать серверу какие-то условия для формирования файла в POST запросе
- На странице мы не размещаем заранее данные в тегах <form></form>, как практикуется в подобных решениях
- Пользователю достаточно нажать на кнопку один раз для получения результата.
В результате скрипт формирования файла может выглядеть примерно следующим образом:
На клиенте:
/**
* Формирование отчета
* @param {type} filename - имя файла на сервере для формирования отчета
* @param {type} ext - выходное расширение (например xlsx,csv)
* @returns {Number}
*/
function get_report(filename,ext){
$("#global").addClass("loading");
var xhr = new XMLHttpRequest();
xhr.open('POST', '?r=reports/'+filename, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.responseType = 'blob';
xhr.onload = function(e) {
$("#global").removeClass("loading");
if (this.status == 200) {
var link=document.createElement('a');
link.href=window.URL.createObjectURL(this.response);
console.log("Расширение:"+ext);
link.download="report."+ext;
link.click();
}
else {
console.log(e);
ToastMessage("error","Произошла ошибка при формировании файла. Попробуйте позднее или обратитесь к администратору системы.");
}
};
var form_data = new Map();
form_data.period_from = period_from.value;
form_data.period_to = period_to.value;
form_data.area = area_select.value;
form_data.division_check=division_check.checked;
form_data.period_check=period_check.checked;
xhr.send(mapToQueryString(form_data));
};
На сервере:
public function actionGet_report_by_settlers(){
$request = Yii::$app->request;
$area= $request->post("area");
$dir=Yii::$app->basePath."/web/templates";
$oSpreadsheet = IOFactory::load($dir . "/report_1_1.xlsx");
...
формируем файл эксель
...
$oWriter = IOFactory::createWriter($oSpreadsheet, 'Xlsx');
$oWriter->save('php://output');
};