Php download script выводит поврежденный файл

Я создавал файл, загружающий класс для моей CMS в PHP, в то время, когда я заметил, что он выводит файлы в другом формате кодирования. Я пробовал с readfile, file_get_contents, fread, но все, похоже, делают то же самое. Это похоже на то, что связано с выходной буферизацией.

Пример файла изображения в формате png, который я загрузил с помощью script, похоже, работает после изменения кодировки с помощью блокнота ++ от UTF до ASCII

Это шаги, которые я сделал до сих пор:

$mime = http::get_file_mime();
header('Pragma: public');   
header('Expires: 0');       
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private',false);
header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Transfer-Encoding: binary');
header('Transfer-Encoding: binary');
header('Content-Description: File Transfer');
header('Content-Encoding: chunked');
header('Connection: closed');
@readfile($this->file);

Я сделал fread:

$file = fopen($this->file,'r');
$read = fread($file,filesize($this->file));
print($read);

Я сделал file_get_contents();

$read = file_get_contents($this->file);
print($read);

Все эти шаги отправляют файл в диалоговое окно загрузки. Но он не выводит файл так, как есть. И это влияет на любой файл, который я пытаюсь загрузить с помощью script.

Что я делаю неправильно?

Ответ 1

Попробуйте запустить ob_start() в первую очередь в script, напишите материал, отредактируйте заголовки, а затем ob_flush() и ob_clean(), когда вы хотите, чтобы ваш контент отправлялся в пользовательский браузер.

Это сработало для меня..

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}

Надеюсь, что это поможет.

Ответ 2

Проблема заключается в заголовке Content-Disposition. Этот заголовок на самом деле не является частью протокола HTTP, см. RFC 2616, 15.5 Проблемы с размещением контента

Content-Disposition не является частью    стандарт HTTP, но поскольку он широко применяется, мы    документируя его использование и риски для разработчиков.

И далее в разделе 19.5.1 Content-Disposition

Поле заголовка ответа Content-Disposition было предложено как    означает, что исходный сервер предложит имя файла по умолчанию, если пользователь    запрашивает, чтобы содержимое было сохранено в файл.
...
Пример:

Content-Disposition: attachment; filename="fname.ext"

Если этот заголовок используется в ответе с приложением/октетом-    потоковый контент-тип, подразумеваемое предположение заключается в том, что пользовательский агент    не должен отображать ответ, но непосредственно вводить ответ сохранения    как... ".

Оставив этот заголовок, вы увидите содержимое отправленного файла.

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