2014-10-31 2 views
0

Я настраиваю скачивание MP3 на своем сайте и хочу, чтобы люди щелкали ссылкой по электронной почте для загрузки ZIP-файла MP3. Я бы хотел, чтобы URL-адрес, который они нажимали, не указывал непосредственно на файл, так что я не показываю фактическое местоположение - я мог бы также добавить ограничение времени для загрузки и т. Д.Любые недостатки использования заголовка («Местоположение: ...») для загрузки файлов?

Так что я использовал файл readfile ($ file_url) и много вариантов заголовка(), но не очень далеко. Затем я прочитал, что вы можете просто использовать:

header("Location: " . $file_url); 

Это похоже на работу в браузерах, которые я тестировал. Есть ли недостаток в том, чтобы делать это таким образом против readfile ($ file_url)?

Спасибо!

ответ

0

«Недостатки» зависит от того, что вы пытаетесь выполнить.

Установив заголовок Location, вы отправляете перенаправление. Браузер, действительно, получит ответ с кодом статуса HTTP 302 («Найдено») и новым URL-адресом ресурса. В основном, вы перенаправляете их на другой ресурс.
Для того, чтобы это сработало, ресурс, на который вы перенаправляете их, должен быть общедоступным. То есть: это должен быть существующий документ внутри «корня документа» вашего сервера.

Этот подход имеет определенные характеристики, которые, в зависимости от ваших требований, могут быть рассмотрены в качестве минусов:

  1. Как написано выше, ресурс должен быть общедоступным. Таким образом, вы не можете хранить файлы MP3 в отдельной, не доступной папке. Действительно, предположим, что ваш корневой каталог документа находится в /var/www/public, вы можете поместить эти файлы в не доступную папку, например /var/www/resources, и обслуживать их только через ваши PHP-скрипты.
  2. Ваши пользователи получат URL-адрес ресурса, и поэтому они смогут напрямую обращаться к ресурсу, не проходя через ваш 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

+0

Большое спасибо - это очень полезно. Я попробовал ваш код (только что изменил Content-Type, чтобы быть «application/zip», поскольку мои MP3-файлы сжаты), но получал zip-файл с нулевым размером файла. Немного больше googling предложил добавить ob_end_flush(), и это, похоже, сделало трюк (даже если я действительно не понимаю почему!). Если бы я мог задать один следующий вопрос: возможно ли сделать страницу (сообщение «ваша загрузка начнется в ближайшее время») во время загрузки, вместо того, чтобы иметь пустую страницу? Я немного экспериментировал, но, похоже, не мог разместить контент где-нибудь рядом с этим ... –

+0

Это просто перенаправление. Сначала вы показываете страницу «загрузка», затем перенаправляете (перенаправление ) на страницу загрузки на php. Ps: zipping mp3 не нужен :) – Qualcuno

+0

А, ок - это проще, чем я думал! Спасибо за вашу помощь. И я зацикливаюсь, потому что это целые альбомы (я старая школа!) –

0

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

На яркой стороне, таким образом, вам не нужно обрабатывать файл через 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'); 
?> 

Просто убедитесь, чтобы не печатать любые string (даже символы BOM UTF8 из вашего исходный код) перед использованием функции Header() < - частая проблема.

+0

Спасибо, Дэвид! Как я уже упоминал в своем другом комментарии, это в значительной степени помогло, как только я добавил ob_end_flush(). Странно, хотя, используя мой оригинальный метод, я никогда не видел, чтобы отображалось фактическое местоположение файла. Я тестировал в Chrome, Safari, FF, IE и во всех них адресная строка не менялась. Итак, не знаете, как пользователь увидит местоположение? Во всяком случае, это академическое, поскольку я, вероятно, сейчас буду с методом readfile()! –

+0

Я считаю, что вы либо совершили какую-то глупую ошибку, либо ваш скрипт напечатал что-то нежелательное. Чтобы проанализировать вторую возможность, вы можете использовать инструмент, подобный этому: http://www.rexswain.com/httpview.html; проверьте, чтобы не печатался нежелательный символ, так как ни один символ не может быть напечатан перед использованием функции header() – David162795

+0

Спасибо Дэвиду - я проверю это, когда буду дальше на своем компьютере. –

Смежные вопросы