[php] Как показать диалог сохранения файла в браузере, вместо его открытия?

Аватара пользователя
Assasin
Сообщения: 104
Зарегистрирован: 17 фев 2011

Код: Выделить всё

header("content-disposition: attachment; filename=file.jpg");
header("content-type: application/x-force-download; name=file.jpg");

если файлов много то

Код: Выделить всё

$file = $_GET['file'];
header("content-disposition: attachment; filename=$file");
header("content-type: application/x-force-download; name=$file");

Аватара пользователя
AgentSIB
Администратор
Сообщения: 329
Зарегистрирован: 17 май 2010
Тема не раскрыта. Второй пример вообще не верен. На доработку.
Frustra fit per plura quod potest fieri per pauciora © Закон "Бритвы Оккама"

Аватара пользователя
Distructor
Администратор
Сообщения: 1604
Зарегистрирован: 28 дек 2009
x-force-download
первый раз о таком слышу. в гугле тоже ничего не нашел.
браузеры судя по всему тоже не понимают, что это такое и как его надо открывать. и потому показывают диалог загрузки.

Аватара пользователя
AgentSIB
Администратор
Сообщения: 329
Зарегистрирован: 17 май 2010
Сань, если передать неясный миме-тип, то всегда будет загрузка, так что особо не важно, что туда будет записано. Есть конечно стандарт и лучше его придерживаться. Но тем не менее использовать нестандартные миме никто не запрещал.
Frustra fit per plura quod potest fieri per pauciora © Закон "Бритвы Оккама"

Аватара пользователя
Assasin
Сообщения: 104
Зарегистрирован: 17 фев 2011
Второе это отсебятину решил добавить не очень удачно. а как редактировать то?

Аватара пользователя
Distructor
Администратор
Сообщения: 1604
Зарегистрирован: 28 дек 2009
если надо отдать несколько файлов, то либо пакуй все в zip и отдавай архивом (агент возможно опишет позже подробнее),
либо по отдавай их одному (т.е. отдал 1, пользователь скачал, нажал "скачать второй" и т.д.).

Аватара пользователя
AgentSIB
Администратор
Сообщения: 329
Зарегистрирован: 17 май 2010
Итак, как раз в этом куске кода. Корректная отдача файла для скачивания:

Код: Выделить всё

$data = file_get_content('/path/to/file');
header('Content-Type: "application/octet-stream"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); // Для IE
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".strlen($data));
exit(
$data);


Загрузка нескольких файлов. Для начала нужно заархивировать например так:

Код: Выделить всё

$files = array('test1.jpg','test2.jpg');
$path = '/path/to/files/';
$archive_filename = 'test.zip';

$zip = new ZipArchive();
if ($zip->open($archive_filename, ZIPARCHIVE::CREATE ) !== true)  {
    exit("cannot open <$archive_filename>\n");
}
foreach(
$file_names as $file){
    $zip->addFile($path.$file, $file);
}
$zip->close();

$data = file_get_content($archive_file_name);

header('Content-Type: "application/octet-stream"');
header('Content-Disposition: attachment; filename="'.$archive_filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); // Для IE
header('Content-Transfer-Encoding: binary');
header('Pragma: public');
header('Content-Length: '.filesize($archive_filename));
exit(
$data);

В этом случае создается zip файл. Более корректно было бы не создавать файлов, однако это сложнее с точки зрения реализации. Директория, в которой создается темповый архив должна быть открыта для записи.
Frustra fit per plura quod potest fieri per pauciora © Закон "Бритвы Оккама"

Аватара пользователя
Assasin
Сообщения: 104
Зарегистрирован: 17 фев 2011
AgentSIB Красавчик :)

Аватара пользователя
Distructor
Администратор
Сообщения: 1604
Зарегистрирован: 28 дек 2009
дополнение

для добавления в архив файлов с русскими названиями, названия следует перевести в досовскую кодировку:

Код: Выделить всё

$filename = iconv('utf-8', 'cp866', $filename); 

ну и соответственно, если вам надо прочитать названия файлов из архива, то меняем кодировку в обратную сторону.

еще один вариант заголовков:

Код: Выделить всё

header('HTTP/1.1 200 OK');
header('Content-Type: application/force-download');
header('Content-Length: ' . filesize($n));
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename="Русское имя файла.txt"');
header('Content-Transfer-Encoding: binary'); 

но стоит учитывать, что старые версии IE заменяют пробелы в названиях скачиваемых файлов на подчеркивания (http://support.microsoft.com/kb/952730/ru).


Вернуться в «PHP»