Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 04.09.2010, 13:39
Новичок на форуме
Отправить личное сообщение для doom_man Посмотреть профиль Найти все сообщения от doom_man
 
Регистрация: 04.09.2010
Сообщений: 3

Открытия ссылки "на скачивания" и отслеживания статус загрузки файла браузером.
Доброе время суток!
У меня возникли сложности в процессе написания не большого 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 отследить, был ли скачен файл или нет? Если бы была возможность, то я бы просто после скачивания файла отправлял бы не большой запрос на сервер с подтверждением скачивания файла, и на сервере удалял бы его из временного каталога.

Помогите, плз может кто сталкивался с подобной задачей
Ответить с цитированием
  #2 (permalink)  
Старый 04.09.2010, 13:57
Аватар для subzey
Пионэр
Отправить личное сообщение для subzey Посмотреть профиль Найти все сообщения от subzey
 
Регистрация: 16.11.2009
Сообщений: 1,322

Чтобы браузер предложил скачать фаил, а не открыл его, нужно отдать его с http-заголовком
Код:
Content-Disposition: attachment
либо
Код:
Content-Disposition: attachment; filename=my_file.tar.gz
Во втором случае браузер предложит сохранить его именно с таким именем.

Все это делается на сервере, естесственно.
Ответить с цитированием
  #3 (permalink)  
Старый 04.09.2010, 14:12
Новичок на форуме
Отправить личное сообщение для doom_man Посмотреть профиль Найти все сообщения от doom_man
 
Регистрация: 04.09.2010
Сообщений: 3

Сообщение от subzey Посмотреть сообщение
Чтобы браузер предложил скачать фаил, а не открыл его, нужно отдать его с http-заголовком
Код:
Content-Disposition: attachment
либо
Код:
Content-Disposition: attachment; filename=my_file.tar.gz
Во втором случае браузер предложит сохранить его именно с таким именем.

Все это делается на сервере, естесственно.
Да, это я уже в гугле вычитал, написал даже уже не большую функцию на php, которая делает правильные заголовки, но обратите внимания, в моем коде я делаю AJAX запрос методом POST, с указанием формата данных JSON и функцией обратного вызова. Т.е. в данном примере если я на стороне сервера скажем сделаю так:

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 вызов ), после чего удалял бы.
Ответить с цитированием
  #4 (permalink)  
Старый 04.09.2010, 15:10
Аватар для subzey
Пионэр
Отправить личное сообщение для subzey Посмотреть профиль Найти все сообщения от subzey
 
Регистрация: 16.11.2009
Сообщений: 1,322

У php есть функция, которая открывает файл и отдает его содержимое клиенту (название не помню, но искать следует рядом с fpassthru). Также, есть функция с названием вроде is_client_aborted, которая проверяет, не отключился ли клиент.

Соответственно, если после вывода содержимого клиент не отключился, то файл скачан.

Сорри, конкретных имен функций не назову - я с телефона.
Ответить с цитированием
  #5 (permalink)  
Старый 04.09.2010, 15:46
Новичок на форуме
Отправить личное сообщение для doom_man Посмотреть профиль Найти все сообщения от doom_man
 
Регистрация: 04.09.2010
Сообщений: 3

Сообщение от subzey Посмотреть сообщение
У php есть функция, которая открывает файл и отдает его содержимое клиенту (название не помню, но искать следует рядом с fpassthru). Также, есть функция с названием вроде is_client_aborted, которая проверяет, не отключился ли клиент.

Соответственно, если после вывода содержимого клиент не отключился, то файл скачан.

Сорри, конкретных имен функций не назову - я с телефона.
так я выше описал что если я делаю GET\POST из AJAX, то что бы я не делал в PHP(имею ввиду с заголовками), то файл не понятно куда скачивается(подозреваю где то в кеше браузера лежит), см. внимательно мой код выше.

Вообщем решил проблему:
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
}


?>
Ответить с цитированием
  #6 (permalink)  
Старый 04.09.2010, 15:56
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Сообщение от doom_man
если я делаю GET\POST из AJAX, то что бы я не делал в PHP(имею ввиду с заголовками), то файл не понятно куда скачивается
Не надо делать ajax-запрос, если хотите скачать файл.
Ответить с цитированием
  #7 (permalink)  
Старый 10.09.2010, 19:16
Аватар для micscr
Профессор
Отправить личное сообщение для micscr Посмотреть профиль Найти все сообщения от micscr
 
Регистрация: 10.09.2009
Сообщений: 1,566

Сообщение от Kolyaj Посмотреть сообщение
Не надо делать ajax-запрос, если хотите скачать файл.
То есть никак - никак?
Ответить с цитированием
  #8 (permalink)  
Старый 10.09.2010, 20:15
Аватар для micscr
Профессор
Отправить личное сообщение для micscr Посмотреть профиль Найти все сообщения от micscr
 
Регистрация: 10.09.2009
Сообщений: 1,566

Создаю в общем файл(надо чтобы у пользователя появилось "Сохранить как" ...), а имя его в сессии. Создал страничку, которая его отдаст:
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()) - не действует.
Ответить с цитированием
  #9 (permalink)  
Старый 10.09.2010, 21:20
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Просто location.href = 'savefile.php';
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Показ статус загрузки файла Орёл AJAX и COMET 9 23.07.2010 18:25