Файлы pdf открываются в браузере? Решение есть!

- Как заставить браузер скачивать pdf, а не открывать в браузере?
- Нужно посылать правильный заголовок.

Не буду заморачиваться на тонкостях mime типов, и того как браузеры эти типы отрабатывают. Замечу, есть три способа загрузки (скачивания) файлов. Может и ещё есть, но я о них не знаю.

Первый способ я не буду описывать, а начну со третьего

Download. Нужно отдать правильный заголовок

Рассмотрим два варианта: серверный и скриптовый (отдельно покажу).

Под серверным я понимаю использование apache, а вернее .htaccess. Т.к. это наиболее удобный способ управления локальным ресурсом


RewriteRule .*\.pdf$ - [L,T=application/octet-stream]

Оапппа. и все работает. Pdf файлы молча скачиваются.

Если хотите - добавляйте свои типы в правило, например


RewriteRule .*\.(pdf|mp3)$ - [L,T=application/octet-stream]

Но!!! А можно и так, переопределить mime тип. Не всегда работает - зависит от настроек хоста

AddType application/octet-stream .mp3
AddType application/octet-stream .pdf

Save as. Нужно отдать правильный заголовок

Увы, одной строчкой не обойдемся, но на это есть другой метод


<IfModule mod_headers.c>
    <FilesMatch "\.pdf$">
		Header set Content-Disposition "attachment"
    </FilesMatch>
</IfModule>

Не буду описывать директив. Цель - отдать правильный заголовок для pdf файла.

Скриптовое решение

Это применимо, если вдруг... не получается управлять сервером. Да-да, случается такое. Но потребуются накладные расходы


/* Оформляем ссылку на скачивние */
<a href="download.php?file=myfile.pdf">


/* Пишем скрипт */
<?php
if (
  !isset($_GET["file"])
  || ($f=$_GET["file"])===false
  || ($fp=@fopen($f,"rb"))===false
  || ($fi=pathinfo($f))===false
  || ($fi["fsize"]=filesize($f))===false
  || strtolower($fi["extension"])!="pdf"
) die("Failed");
 
ob_start();
header("Accept-Ranges: bytes");
header("Content-Length: {$fi["fsize"]}");
header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename="{$fi["basename"]}"");
 
$sent = 0;
while ( !feof($fp) && $sent < $fi["fsize"] && ($buf = fread($fp, 8192)) != "" ){
  echo $buf;
  $sent += strlen($buf);
  flush();  ob_flush();
}
fclose($fp);
exit;
?>


Добавив, дополнительный параметр в запрос, напрмер type=download или type=saveas определяющий тип закачки, скрипт получится универсальным.

Основной материал обработан из 3 Ways to Serve PDF Files using Htaccess Cookies, Headers, Rewrites Там есть все интересующие примеры и решения.

ps. На самом деле эта статья написана чтобы только не потерять нужную ссылку.