[Решено] Не получается корректно отдать файл на php

Главные вкладки

Аватар пользователя -pax- -pax- 7 июня 2010 в 16:53

Пытаюсь организовать отдачу файла пользователю таким скриптом:

<?phpheader("Content-Disposition: attachment; filename=file.exe");
header("Content-Type: application/octet-stream");
readfile("file.exe");
?>

Если использовать такой код в отдельно созданном файле на хостинге, то все работает, но когда я вставляю этот текст в ноду друпала через фильтр PHP code, exe файлы перестают корректно скачиваться.

Файл скачивается, но "портиться" и перестает запускаться.
zip файлы при этом скачиваются и работают корректно.

Подскажите куда копать?

Комментарии

Аватар пользователя -pax- -pax- 7 июня 2010 в 18:38

"xxandeadxx" wrote:
свой модуль с MENU_CALLBACK

Вы предлагаете делать свой модуль?

Я бы хотел разобраться, что мешает этому коду работать корректно в друпале и как-то решить эту проблему...

Аватар пользователя xxandeadxx xxandeadxx 7 июня 2010 в 18:42

"-pax-" wrote:
Вы предлагаете делать свой модуль?

да

"-pax-" wrote:
Я бы хотел разобраться, что мешает этому коду работать корректно в друпале

html код страницы который выводится прежде чем обработается php код в ноде

"-pax-" wrote:
и как-то решить эту проблему...

"xxandeadxx" wrote:
свой модуль с MENU_CALLBACK

Аватар пользователя -pax- -pax- 7 июня 2010 в 19:32

"direqtor" wrote:
Добавьте в скрипт exit()

Если добавить перед выводом кода exit(), то отдача файла вообще перестает работать, белый экран...

Может кто-нибудь объяснить, почему в моем случае файлы zip отдаются корректно, а файлы exe нет?

Аватар пользователя Vladimir_VVV Vladimir_VVV 7 июня 2010 в 19:56

Проблема в том что хидер отправляете на скачку а выдаете содержимое файла внутри всей страницы 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");
?>

Опятьже спасибо мне в виде стотыщьпиццот баксов

Аватар пользователя -pax- -pax- 7 июня 2010 в 19:58

"Vladimir_VVV" wrote:

Точно открыл получаемый zip файл блокнотом, а там html-код Smile Спасибо большое за объяснение, теперь хоть понял с чем бороться надо.

Аватар пользователя direqtor direqtor 7 июня 2010 в 20:48

"-pax-" wrote:
Если добавить перед выводом кода exit(), то отдача файла вообще перестает работать, белый экран...
Тут подумал, что и после кода exit ставить бессмысленно. PHP код исполняется с перехватом данных из буфера, так что содержимое файла в любом случае попадёт внутрь переменной шаблона. Сорри. Вам или решение Владимира подойдёт или модификация того, на что я приводил ссылки.

Аватар пользователя -pax- -pax- 7 июня 2010 в 23:22

Сделал свой модуль как тут http://shaman.asiadata.ru/node/108 все получилось Smile

Спасибо direqtor за ссылку и Vladimir_VVV за объяснение сути проблемы.

Вот содержание модуля, может пригодиться кому-нибудь Wink


<?php 
function smspartner_menu() {

 

$items['download'] = array(
    
'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. Мой первый модуль для друпала Smile

Аватар пользователя Vladimir_VVV Vladimir_VVV 8 июня 2010 в 0:09

есть еще простой вариант, я просто немного усложнил написав вначале пост, а потом подумал и вспомнил что друпал выводит на печать через 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!!!