Открытия ссылки "на скачивания" и отслеживания статус загрузки файла браузером.
Доброе время суток!
У меня возникли сложности в процессе написания не большого JavaScript-а, а именно, есть некий процесс: - пользователь выделяет файлы на web странице, JS обрабатывает это выделение, получает ID элемента( для каждого файла оно будет уникальным), собирает массив JS, перевожу его этот объект в формат JSON и отправляю данные на сервер (не большой PHP скрипт) - сервер получив эти данные обрабатывает, выбирает нужные файлы по ID (полная информация о файлах храниться в БД). Упаковывает выбранные файлы в архив zip и перемещает во временную public директорию для скачивания, дальше серверный сценарий отвечает обратно в браузер в формате JSON, в одном из параметров как раз и будет ссылка на этот архив. Вот как это выглядит у меня: function GetSelectedFiles(id){ if(id){ selectedIDs.length = 0; uncheckSelection(); selectedIDs.push(id); } if(selectedIDs.length > 0 ){ oSendingData.file_list = selectedIDs; $.post(php_download_link,JSON.stringify(oSendingData),onDownload,'json'); } else{ printStatusbar("Выберите файл(ы) для скачнивания"); } // Если скачиваем по иконки, то отчищаем массив if(id) selectedIDs.length = 0; function onDownload(responce_json){ // Проверка ответа от сервера checkAuthAndError(responce_json); // Если получили ссылку на файл! window.location.href = responce_json.download_link; }; }; Собственно в чем проблема, после того как скрипт получил данные от сервера, я отдаю ссылку на «временный» файл в браузер, что бы конечно пользователь мог её скачать, это происходит вот в этой строке: window.location.href = responce_json.download_link; Так вот именно тут возникают две не понятки. 1) Если я даю ссылку не в на .ZIP архив, а на файл .JPEG, то браузер почему то открывает эту ссылку в ЭТОМ же окне и отображает картинку в браузере. Возможно ли как-нибудь заставить браузер открывать ссылку всегда с предложением для скачивания? 2) Пока временные файлы лежат во временном каталоге и я их удаляю периодический в ручную, думал вешать на сервере скрипт на perl\bash\php под cron-ом, который удалял бы файлы через N-кол-во времени, но это не совсем хороший способ, по многим причинам. Итак вопрос, возможно ли при помощи JS отследить, был ли скачен файл или нет? Если бы была возможность, то я бы просто после скачивания файла отправлял бы не большой запрос на сервер с подтверждением скачивания файла, и на сервере удалял бы его из временного каталога. Помогите, плз может кто сталкивался с подобной задачей :victory: |
Чтобы браузер предложил скачать фаил, а не открыл его, нужно отдать его с http-заголовком
Код:
Content-Disposition: attachment Код:
Content-Disposition: attachment; filename=my_file.tar.gz Все это делается на сервере, естесственно. |
Цитата:
header('Pragma: public'); // required header('Expires: 0'); // no cache header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($file_name)).' GMT'); header('Cache-Control: private',false); header("Content-Type: application/zip\n"); header('Content-Disposition: attachment; filename="'.basename($file_name).'"'); header('Content-Transfer-Encoding: binary'); header('Content-Length: '.filesize($file_name)); header('Connection: close'); readfile($file_name); То в браузер почему то этого не понимает, хотя если я сделаю GET\POST к серверному файлу в ручную, то браузер нормально понимает этот HTTP заголовок. Да и кроме того в моем случае в ответе от сервера (в формате JSON), существует еще дополнительная информация кроме как ссылка на файл. Хотя я тут сейчас подумал, может быть действительно сделать дополнительную обработку данных с сервера, и отдельный сценарий на сервере который принимал бы данные о файле в GET-е отдавал их на скачку(как-нибудь в так: window.location = 'get_file.php?filename=XXXX.zip', т.е. что бы не использовать AJAX вызов ), после чего удалял бы. |
У php есть функция, которая открывает файл и отдает его содержимое клиенту (название не помню, но искать следует рядом с fpassthru). Также, есть функция с названием вроде is_client_aborted, которая проверяет, не отключился ли клиент.
Соответственно, если после вывода содержимого клиент не отключился, то файл скачан. Сорри, конкретных имен функций не назову - я с телефона. |
Цитата:
Вообщем решил проблему: var sname = getParam("sname"); var sid = getParam(sname); var add_url = 'PHPSESSID=' + sid + '&sname=' + sname; var php_get_dl_link = '../php/json_get_file.php'; var php_download_file = '../php/download.php?' + add_url; var oSendingData = new Object(); oSendingData.session_id = sid; oSendingData.session_name = sname; function GetSelectedFiles(id){ if(id){ selectedIDs.length = 0; uncheckSelection(); selectedIDs.push(id); } if(selectedIDs.length > 0 ){ oSendingData.file_list = selectedIDs; $.post(php_get_dl_link,JSON.stringify(oSendingData),onDownload,'json'); } else{ printStatusbar("Выберите файл(ы) для скачивания"); } // Если скачиваем по иконки, то отчищаем массив if(id) selectedIDs.length = 0; function onDownload(responce_json){ // Проверка ответа от сервера checkAuthAndError(responce_json); // Если получили ссылку на файл! window.location.href = php_download_file + '&dl_file='+responce_json.download_link; }; }; json_get_file.php // Тут идет обработка файла, проверка авторизации и так далее .... // Сохраняю путь к временному файлу, что бы его ни кто другой не спер! $_SESSION['download_tmp_file'] = $file_name; // ..... ну и потом сам download.php <?php ini_set('display_errors',1); error_reporting(E_ALL); ini_set('session.use_cookies',0); // Подключаю настройки include("./include/g_settings.inc.php"); $sname = $_GET['sname']; $sid = $_GET['PHPSESSID']; $filename = $_GET['dl_file']; session_id($sid); session_name($sname); session_start(); // Запускам сессию // Проверяем что сессия активна! if(!isset($_SESSION['is_auth']) || $_SESSION['is_auth'] == 0){ // Если сессия не активна $s_status = 0; session_unset(); session_destroy(); Header("Location: ../index.html"); exit(1); } // Если установлена переменная сессия с ссылкой на скачку файла if(isset($_SESSION['download_tmp_file'])){ // Проверяем что поступил запрос на скачку именно этого файла! if($_SESSION['download_tmp_file'] == $filename){ header('Pragma: public'); // required header('Expires: 0'); // no cache header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($filename)).' GMT'); header('Cache-Control: private',false); header("Content-Type: application/zip\n"); header('Content-Disposition: attachment; filename="'.basename($filename).'"'); header('Content-Transfer-Encoding: binary'); header('Content-Length: '.filesize($filename)); header('Connection: close'); // Отдаем файл в браузер ob_clean(); flush(); if(readfile($filename)){ if(!unlink($filename)) // Удаляем файл, если не получилось то сообщаем об ошибки echo "<h1>Error on remove file! Please contact a system administrator!</h1>"; // TODO: syslog else unset($_SESSION['download_tmp_file']); // Хотя все равно перезапишется! } else echo "<h1>Error on download file! Please contact a system administrator!</h1>"; // TODO: syslog } else { echo "<h1>access denied!!!</h1>"; // TODO: syslog } }else{ echo "<h1>File not found!!!</h1>"; // TODO: syslog } ?> |
Цитата:
|
Цитата:
|
Создаю в общем файл(надо чтобы у пользователя появилось "Сохранить как" ...), а имя его в сессии. Создал страничку, которая его отдаст:
session_start(); $f = (isset($_SESSION['loadfile'])) ? $_SESSION['loadfile'] : 'xxx.xxx'; unset($_SESSION['loadfile']); if (file_exists('./data/' . $f)) { header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment;filename=" . $f); echo file_get_contents('./data/' . $f); } В своем же ajax-приложении, мне надо открыть этот адрес. Делаю так: var w = window.open('savefile.php'); появляется окошко о заблокированных окнах. Можно как то лучше это сделать? Пробовал ссылку с target="_blank" на jQuery кликнуть($('#aaa').click()) - не действует. :( |
Просто location.href = 'savefile.php';
|
Часовой пояс GMT +3, время: 09:37. |