Уже неоднократно сталкивался с задачей выведения пользователю на скачивание файлов, залитых в качестве свойств инфоблока... И если это самое свойство ставить с типом "Файл" то битрикс автоматически данному файлу присваивал уникальное имя, конфликта файлов в системе не возникало, но вот выдавать этот файл было крайне проблематично.
До недавнего времени вместо свойства "Файл" ставил другое - "Привязка к файлу на сервере" и тогда по ИД файла вытягивалось его имя, файл выдавался на скачивание и все было просто замечательно.
Но, в один прекрасный момент, возникла задача и необходимость более профессионального подхода к данному вопросу и вот решил сделать полноценный механизм по закачке/скачке файлов.
Итак, сама задача:
Пользователь сайта через компонент добавления нового элемента ИБ добавляет свой элемент. Одним из свойств элемента является поле "Файл" с типом "Файл". Дальше этот элемент через вывод списка новостей выводим другим пользователям. Файл должен быть доступен для скачивания с тем именем, с которым его заливали, а не с той "кракозяброй", с которой он хранится на сервере.
Решение:
Заливка файла проходит нормально, обычным образом, поэтому на ней останавливаться не буду.
Вывод элементов происходит с помощью стандартного компонента news.list. При выводе элементов, когда добираемся до свойства с файлом, получаем всего-лишь ИД файла и ничего больше.
Т.к. у меня таких файлов могло быть несколько, то данный блок получился такой:
Тут мы делаем перебор по всем файлам, добавленным в данное свойство элемента. Получаем файл по его ИД. Для отображения пользователю нормального, читабельного имени, получаем имя, с которым данный файл был загружен на сервер:
$arFile["ORIGINAL_NAME"]
Дальше выводим ссылку пользователю на скачивание файла:
Скачивание файла не напрямую, а через другой вспомогательный файл со скриптом, было сделано сначала просто потому, что пользователю файл при сохранении выдавал все-таки не то имя, которое мы отображаем, а то, с которым он хранится на сервере и с этим надо было как-то бороться. Вот и пришел к решению, что нужно создать доп. файл, в котором будет определяться нужное имя файла. Этому скрипту передаем ИД файла, который нужно скачать...
Скрипт начинается со строки, в которой мы проверяем указан ли вообще ИД файла:
<? if(isset($_GET['file'])){
Дальше мы снова получаем оригинальное имя файла и транслитерируем его. В Данной транслитерации учтены символы русского и украинского языка. Кому нужны еще какие-то символы - добавляйте.
Для того, чтобы построить нужную нам схему html-файла, которая будет нам выдавать файл на скачивание, нужно указать соответствующие head-функции. Все данные для этих функций можно выбрать из свойств файла. Что в принципе и было сделано...
Битриксовая функция получения пути файла выдает путь не физический (где файл лежит на сервере), а путь относительно корня сайта. поэтому к пути нужно добавить где сайт лежит физически на сервере.
Теперь построчно самый важный кусок всего скрипта:
Имя файла, которое будет выдано пользователю при сохранении:
Тип файла - нужен в основном для того, чтобы браузер понимал, что делать с этим файлом:
header("Content-Type: $c_Type");
Непосредственное чтение файла:
readfile($file);
Уже после реализации, осознал несколько преимуществ такого скачивания.
Во-первых, это конечно же транслитерация названия файла. Она является достаточно важным моментом данной реализации, т.к. не все браузеры нормально реагируют на кириллицу.
Во-вторых, пользователь никак не может получить прямую ссылку на файл. И если внутри скрипта поставить доп. проверку на то, а может ли текущий пользователь скачивать этот файл, то воспользоваться прямой ссылкой без авторизации на сайте уже будет очень проблематично...
Update 2015-08-04: Рекомендую файл-обработчик скачивания начинать не с
Vadim Dumbravanu обнаружил уязвимость в приведенном скрипте, рекомендую ознакомиться с выводами по уязвимости и принять свое собственное решение, что с этим делать. У меня, к сожалению или счастью, нет проектов, на которых есть необходимость в данном скрипте, но, возможно, кому-то будет полезно.
Итак! Скрипт содержит критическую уязвимость, поэтому в приведенном виде не может быть использован в конечных проектах. Описание уязвимости:
1) перебором ID можно выкачать все загруженные файлы - а вы не можете знать, какие из них защищены по доступу 2) можно указать путь к файлу - т.к. к целому значению параметр не приводится, то скачается любой произвольный файл, включая dbconn.php с паролем к БД К сожалению, этот уязвимый скрипт уже разошелся по ряду проектов. Если Вы лично имеете отношение к таким проектам, рекомендую срочно внести правки, либо удалить этот скрипт на них.
Могу порекомендовать: 1) Передавать не только ID картинки, но и ID элемента инфоблока и проверять, что в этом элементе есть эта картинка 2) все параметры приводить к целому.
1. докачки нет. посмотрите хотя бы битриксовский родной, например, bizproc_show_file.php 2. зачем транслит? какие браузеры не понимают кириллицу? просто интересно. проблема с ИЕ решается через:
зы. в общем, решение есть в самом битриксе, можно там подсмотреть, если интересно. просто не распространяется на стандартный вывод свойств типа файл (да и не только) в компонентах типа ньюз, не понятно почему, тоже раздражает. с учётом вышеизложенного предлагаю доработать пост, возможно будет хорошим подспорьем новичкам, организующим скачивание файла не напрямую. ззы. также советую ознакомиться с методом CIBlockFormatProperties::GetDisplayValue, посёрчить "контролируемое скачивание" на форуме, зайти сюда, и ещё что-то поиск тупит, не так давно, в пределах полугода назад где-то был нормальный пример защищённого хранения/скачивания файлов в двухуровневой конфигурации с nginx тоже.
я вообще не поняла зачем вся эта морока? есть галочка в настройках главного модуля "оставлять оригинальные имена файлов", есть DISPLAY_VALUE в котором уже готовая ссылка на файл, а также есть GetFileArray которая по ИД файла выдаст все его свойства, в том числе и путь, если необходимо самому сформировать эту ссылку...
Поясню. Есть 2 вида свойств ИБ для работы с файлами: "Файл" и "Привязка к файлу". Вариант "Привязка к файлу" прост и о нем можно даже и не говорить. А вот вариант "Файл" - при загрузке автоматом перебивает название файла в уникальное (при этом в свойствах файла истесно сохраняется оригинальное название). Вот как раз для этого второго случая я и делал данный финт ушами.
Я более чем уверен, что всегда можно найти более оптимальное решение. Но когда мне срочно нужно было сделать скачивание файла и ничего понятного найти не смог - мне бы таковой пост пригодился....
Так что, как сказал Евгений, "пост, возможно будет хорошим подспорьем новичкам, организующим скачивание файла не напрямую" А по поводу его доработки - пишите в комментах если кто-то придумает, что и как можно тут оптимизировать...
По поводу "Зачем транслит" - знакомый прогер сказал, что так надежнее, вот и поставил.... Сайт, для которого делал, слишком серьезный, поэтому решил, что нужно.
по поводу "Докачки нет": в моем случае файлы - это скриншоты, краткие описание в форматах офиса....
ко мне обратились с вопросом по данному скрипту. думаю это будет интересно всем:
xxx (10:14:41 15/12/2011) я наткнулся на вашу статью "Как я делал механизм скачивания файлов." xxx (10:14:59 15/12/2011) но возникла проблемма xxx (10:15:44 15/12/2011) фаил в моём случае картинка, скачевается испорченой xxx (10:16:05 15/12/2011) те в код файла добавляется код хедера и футера xxx (10:16:17 15/12/2011) как можно этого избежать?? Попович Алексей (10:16:17 15/12/2011) а шаблон пустой применили? Попович Алексей (10:16:34 15/12/2011) шаблон для этого скрипта должен быть абсоллютно пуст (состоять ТОЛЬКО из #TEXTAREA#) xxx (10:17:28 15/12/2011) у меня, детальная страница вывода инфы и ссылка на фаил, данный скрипт Попович Алексей (10:17:52 15/12/2011) вот именно к данному файлу-скрипту и нужно применять пустой шаблон xxx (10:18:37 15/12/2011) не совсем понял как это сделать xxx (10:19:56 15/12/2011) создал новый файл и воткнул туда код скрипта xxx (10:20:30 15/12/2011) ссылка направленна на этот фаил + передача ID Попович Алексей (10:20:50 15/12/2011) Рабочий стол-Настройки-Настройки продукта-Сайты-Список сайтов - Ваш сайт. Внизу есть поле "Шаблон" и там указываете в качестве шаблона - пустой (абсоллютно), тип условия - для папки или файла в условии - полный путь к файлу скрипта Попович Алексей (10:21:01 15/12/2011) пустой шаблон обычно есть в поставке...
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».