Я настраиваю загрузки MP3 на своем сайте и хочу, чтобы люди нажимали на ссылку в электронном письме, чтобы загрузить ZIP-файл MP3. Мне бы хотелось, чтобы URL-адрес, по которому они щелкали, не указывал непосредственно на файл, чтобы я не раскрывал фактическое местоположение — я мог бы также добавить ограничение по времени загрузки и т. Д.
Поэтому я использовал readfile ($ file_url) и пробовал много опций header (), но не очень далеко зашел. Тогда я читаю, вы можете просто использовать:
header("Location: " . $file_url);
Кажется, это работает нормально в браузерах, которые я тестировал. Есть ли недостаток в том, чтобы делать это по сравнению с readfile ($ file_url)?
Спасибо!
«Недостатки» зависят от того, чего вы пытаетесь достичь.
Установив Location
заголовок, вы отправляете перенаправление. Браузер, действительно, получит ответ с кодом состояния HTTP 302 («Найдено») и новым URL ресурса. По сути, вы перенаправляете их на другой ресурс.
Чтобы это работало, ресурс, на который вы перенаправляете их, должен быть общедоступным. То есть: это должен быть существующий документ внутри «корня документа» вашего сервера.
Этот подход имеет определенные характеристики, которые, в зависимости от ваших требований, может следует рассматривать как недостатки:
/var/www/public
вы можете поместить эти файлы в недоступную папку, например /var/www/resources
и обслуживать их только через ваши скрипты PHP.Если эти «характеристики» не подходят для вас, вы можете избежать использования Location
заголовок.
Некоторый код PHP для обслуживания файлов MP3 может быть:
$file = 'local/path/to/your_audio_file.mp3'; // the path on the local file system - ie. don't use "http://www.example.com"!
header('Content-Description: File Transfer');
header('Content-Type: audio/mpeg'); // audio/mpeg is the correct mime type for mp3 files
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));
readfile($file);
exit; // Could be a good idea to exit at the end
Некоторые заголовки могут быть избыточными, но они обеспечивают лучшую кросс-браузерную совместимость. Я взял их (а затем адаптировал) из http://php.net/manual/en/function.readfile.php
Нет серьезных проблем, просто вы фактически указываете фактическое местоположение файла (злоумышленник может попытаться угадать адреса файлов, к которым он не должен иметь доступ), клиент должен будет сделать дополнительный запрос к серверу (задержка загрузки всего на несколько миллисекунд), а иногда У веб-обозревателя плохой день и он решает не следить за переездом по разным причинам.
С другой стороны, таким образом вам не нужно обрабатывать файл через PHP, сохраняя крошечные ресурсы сервера (что весьма сомнительно, поскольку функция readfile () довольно оптимизирована по сравнению с обработкой нового http-запроса)
Возвращаясь к исходной проблеме, при подаче файла для загрузки через PHP вам не нужно ничего больше, чем 3 строки из следующего примера:
<?php
//code copied from http://php.net/manual/en/function.header.php
// We'll be outputting a PDF
header('Content-type: application/pdf');
// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');
// The PDF source is in files/originalfile.pdf
readfile('files/originalfile.pdf');
?>
Просто убедитесь, что вы не печатаете ни одной строки (даже символов спецификации UTF8 из вашего исходного кода) перед использованием функции Header () <частая проблема.