Пытаюсь организовать отдачу файла пользователю таким скриптом:
<?phpheader("Content-Disposition: attachment; filename=file.exe");
header("Content-Type: application/octet-stream");
readfile("file.exe");
?>
Если использовать такой код в отдельно созданном файле на хостинге, то все работает, но когда я вставляю этот текст в ноду друпала через фильтр PHP code, exe файлы перестают корректно скачиваться.
Файл скачивается, но "портиться" и перестает запускаться.
zip файлы при этом скачиваются и работают корректно.
Подскажите куда копать?
Комментарии
свой модуль с MENU_CALLBACK
Вы предлагаете делать свой модуль?
Я бы хотел разобраться, что мешает этому коду работать корректно в друпале и как-то решить эту проблему...
да
html код страницы который выводится прежде чем обработается php код в ноде
А что должен делать этот модуль?
о_О ну скорей всего
нет?
Эх если бы кто-нибудь на более понятном языке объяснил...
Добавьте в скрипт exit()
Не помню где здесь писал про отдачу картинок, давно это было, но может в доках осело
У себя http://shaman.asiadata.ru/node/108
Можно сделать по аналогии, только MIME-тип сменить надо
Если добавить перед выводом кода exit(), то отдача файла вообще перестает работать, белый экран...
Может кто-нибудь объяснить, почему в моем случае файлы zip отдаются корректно, а файлы exe нет?
Проблема в том что хидер отправляете на скачку а выдаете содержимое файла внутри всей страницы drupal, то есть там и <html> и <body> и тд и тп.
Зип файлы отдаются так же только архиватор в состоянии увидеть сигнатуру зипфайла не в начале файла а внутри ....<div class="content">Rar!.....</div> , а эксешный файл должен начинаться именно с сигнатуры MZ а начинается с <!DOCTYPE html... а сигнатура MZ только в опять же ... <div class="node"><div class="content">MZ....
Вам только через менюколбэк можно сделать чистый вывод или (череззадный способ но простой)через создание шаблона перекрытия.
Например у вас пхп-нода с номером 2082? адрес /node/2083
создаете в своей теме файл page-node-2082.tpl.php с содержимым
<?php print $content ;
?>
а в файле node.tpl.php в самое начало вставить
<?php
if($node->nid==2082)
{
print $content;
exit;
}
?>
теперь отключаем тему и заново включаем, и усе, ваш файл качается.
Ну и на последок поправка, хидеры лучше отправлять drupal-функциями, например
<?php
// Send Header
drupal_set_header("Pragma: public");
drupal_set_header("Expires: 0");
drupal_set_header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
drupal_set_header("Content-Type: application/force-download");
drupal_set_header("Content-Type: application/octet-stream");
drupal_set_header("Content-Type: application/download");
drupal_set_header("Content-Disposition: attachment;filename=file.exe");
drupal_set_header("Content-Transfer-Encoding: binary "); readfile("file.exe");
?>
Опятьже спасибо мне в виде стотыщьпиццот баксов
Точно открыл получаемый zip файл блокнотом, а там html-код Спасибо большое за объяснение, теперь хоть понял с чем бороться надо.
Сделал свой модуль как тут http://shaman.asiadata.ru/node/108 все получилось
Спасибо direqtor за ссылку и Vladimir_VVV за объяснение сути проблемы.
Вот содержание модуля, может пригодиться кому-нибудь
<?php
function smspartner_menu() {
'type' => MENU_CALLBACK,
'page callback' => 'smspartner_file',
'access arguments' => array('access content'),
);
return $items;
}
function
smspartner_file($file='') {drupal_set_header("Content-Disposition: attachment; filename=$file");
drupal_set_header("Content-Type: application/octet-stream");
readfile("/путь к файлу на сервере/$file");
exit();
} ?>
потом в нужном месте вызываю: smspartner_file(file.exe)
и запускается скачивание файла file.exe из папки указанной в модуле
делал все это для отдачи файлов за смс
PS. Мой первый модуль для друпала
есть еще простой вариант, я просто немного усложнил написав вначале пост, а потом подумал и вспомнил что друпал выводит на печать через ob_start(); а это сильно упрощает дело.
И так все что я писал выше - забудте, никаких изменений в файлах шаблона ненужно:
пишем в своей ноде с PHP-фильтром:
<?php
ob_get_contents();// типо получаем все что до этого нарендерил drupal
// и никуда его не отправляем, и никакой переменной неприсваиваем
// далее обычные хидеры для скачки файла
drupal_set_header("Pragma: public");
drupal_set_header("Expires: 0");
drupal_set_header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
drupal_set_header("Content-Type: application/force-download");
drupal_set_header("Content-Type: application/octet-stream");
drupal_set_header("Content-Type: application/download");
drupal_set_header("Content-Disposition: attachment;filename=file.exe");
drupal_set_header("Content-Transfer-Encoding: binary "); readfile("file.exe");// соственно выводим это
exit; // и завершаем работу скрипта, больше ничего ненужно
?>
Вот таким образом можно послать на скачку в виде файла, любой контент через обычную ноду с форматом ввода PHP.
Нет ничего проще drupal`a!!!