Как загрузить файл на сайт drupal

Обновлено: 06.07.2024

CDN (Content Delivery Network) — это распределенная инфраструктура для доставки статичных файлов, имеющая ряд преимуществ по сравнению с привычными способами хранения.

Физически CDN — это несколько географически распределенных файловых и проксирующих серверов, оптимизированных для скачивания файлов, в том числе в очень больших объемах.

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

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

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

Небольшое вступление

Я занимаюсь поддержкой открытого проекта Метро 2-х столиц, и уже достаточно давно собирался выложить его исходный код в открытый доступ, чтобы любой желающий смог развернуть проект у себя и, при желании, помочь в разработке.

Основной объем сайта составляют фото, порядка 2 Гб. Да, объем по современным меркам не большой, но в систему контроля версий его не загрузишь. Можно было бы попробовать использовать проксирование, но мне всегда хотелось отвязать контент от файлов сайта, и это ли не хорошая задача для CDN?

Вот вам и первый сценарий использования.

Так же отмечу, что в нашей студии 4D design мы поддерживаем множество проектов, в том числе хостим на своих серверах, разворачиваем по несколько копий проекта для тестирования и публикаций обновлений, и перенос статических файлов в CDN может существенно упростить процесс работы с проектами, где используется много файлового контента.

Еще один очевидный сценарий — очень большие объемы данных, которые было бы просто не рентабельно хранить на сервере вместе с самим сайтом.

Краткий обзор CDN провайдеров

CDN сейчас очень популярен и востребован, предложений много, есть из чего выбрать. Наиболее известные провайдеры — это, пожалуй, Cloudflare, KeyCDN, Amazon CloudFront.

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

Я же для себя выбрал решение от DigitalOcean — Spaces. На DigitalOcean (далее DO) мы хостим наши проекты, доверяем ему свои данные и пока проблем не было, все четко и просто. Со Spaces все тоже довольно просто, один тариф — 5$ в месяц за 250 Гб.

Кстати, для новых пользователей DO сейчас доступны приветственные 100$, которые действуют в течение 2-х месяцев. Так же их можно получить, если зарегистрироваться по моей реферальной ссылке.

Настройка DigitalOcean Spaces CDN

На самом деле Spaces — это хранилище объектов (файлов), а встроенный CDN — это дополнительная возможность, которая, кстати, появилась не сразу. Похожий принцип используется и в Amazon CloudFront, где в роли хранилища выступает сервис Amazon Simple Storage Service (S3).

Забегая вперед, скажу, что Spaces использует протокол S3 для загрузки файлов в хранилище, но давайте сначала активируем и настроим само хранилище.


Создание Space

Процесс довольно простой. Нужно выбрать регион основного центра хранения данных, тип хранилища — публичный или приватный и уникальное название для хранилища. На момент публикации статьи было доступно 3 региона: США, Сингапур и Нидерланды. Так же есть возможность сразу же активировать функцию CDN.


Добавление поддомена для CDN

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

Хранилище создано, и мы можем увидеть адреса, по которым к нему можно обратиться. Самое важное тут:

И осталось только получить пару ключ/секрет для доступа на загрузку файлов с помощью сторонних клиентов. Это делается в разделе "API", секция "Spaces access keys".

Файлы в хранилище можно загружать через веб-интерфейс, с помощью API, с помощью сторонних клиентов — Transmit, Cyberduck, FileZilla Pro, консольного клиента s3cmd и прочих, поддерживающих протокол S3. Мы же будем интегрироваться с Drupal.

Если останутся вопросы можно воспользоваться шикарной документацией.

Использование CDN в Drupal 8

Общий принцип использования CDN для файлов сайта будет такой: загрузить файлы в CDN и сделать так, чтобы URL на сайте указывали на эти файлы.

  • Вариант 1: если URL файлов формируются вручную, например трудолюбивым контент менеджером, то и загружать файлы придется тоже вручную, но думаю, что это редкий случай.
  • Вариант 2: если URL файлов формируются Drupal, например при загрузке файла через поле, то в идеале, конечно, хотелось бы, чтобы Drupal загружал в CDN и сам файл.
  • Вариант 3: URL файлов на сайте заменяются на URL файлов в CDN, но о загрузке самих файлов вам придется позаботиться самому.

Модуль CDN для Drupal

Первое что нашлось в интернете по теме — это модуль CDN. Как оказалось в нем реализован третий вариант, то есть модуль ничего сам в CDN не загружает. Вы можете управлять только тем, какие именно URL будут заменяться.

Этот вариант можно автоматизировать, например примонтировав CDN в папку, в которую загружаются файлы. Вот проект, который позволяется реализовать такую схему.

Возможно, это будет самый быстрый вариант по скорости, но мне он показался не самым удобным, и я продолжил свои исследования.

Обновление

На самом деле модуль CDN предназначен для использования с CDN с поддержкой функции Origin Pull. Это технология, которая настраивается на стороне CDN сервиса и берет на себя всю работу по загрузке файлов. То есть она отслеживает обращения к файлам на сайте и подгружает их в хранилище CDN. Это самый простой и, как оказалось, довольно распространенный вариант использования, но, к сожалению, Spaces эту функцию не поддерживает.

Модуль S3 File System

S3 File System — это второй по популярности модуль имеющий версию для Drupal 8, после модуля CDN. В нем используется второй вариант, при этом вся папка публичных (и/или приватных) файлов может быть перенесена в CDN. Такой подход интересен тем, что помимо файлов, загружаемых в поля, из CDN будут так же передаваться файлы CSS и JS. Это может быть и преимуществом, и недостатком, в зависимости от того, как часто эти файлы обновляются на сайте. Как рекомендуют в самом модуле, кеш шаблонов при этом лучше вынести в другую папку, с помощью настройки в файле settings.php (там же прописывается пара ключ/секрет для доступа Drupal к CDN на загрузку файлов).

Альтернативный вариант — использовать хранилище только для определенных полей. Этот вариант, пожалуй, наиболее актуальный.

Несмотря на статус альфа, модуль довольно интересный, правда мне не удалось проверить его в боевых условиях.

Обновление

Сначала я остановился на решении описанном в следующей части статьи, но потом все же решил вернуться к этому модулю. Для сохранения естественного порядка повествования, рекомендую сначала прочитать две следующих части, а потом вернуться к тексту ниже.

Неприемлемая скорость загрузки некешированных страниц при использовании модулей Flysystem, сподвигла меня более детально рассмотреть и опробовать этот модуль.

Принципиально модули не сильно отличаются, даже используют одинаковое название для хранилища по умолчанию — s3 (это, кстати, позволило мне очень быстро переключиться на этот модуль). Но в S3 File System используется другая библиотека — AWS SDK.

Основные настройки модуля производятся в интерфейсе администрирования, а зависимые от окружения — в файле settings.php .


Основные настройки модуля S3 File System

Здесь указываются имеющиеся у нас параметры хранилища: я использовал настройку "Use a Custom Host", где указал свой "endpoint". Также указаны "bucket", синоним, корневая папка, а вот регион в случае использования Custom Host — не играет роли.

Настройки в файле settings.php :

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

На этом настройка завершена, правда для полноценной работы потребовалось применить патч, который решает проблему со ссылками при первичной генерации стилей изображений.

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

Как и в модуле Flysystem, проблема не удаляемых после загрузки временных файлов, к сожалению, тут тоже имеет место быть.

Модули Flysystem и Flysystem - S3

Модуль Flysystem и расширение к нему Flysystem - S3 мне показались наиболее перспективным решением. Тут также применятся второй вариант работы с CDN, реализована поддержка хранилищ для определенных полей, а в качестве кодовой базы используется многообещающая библиотека Flysystem.

Помимо S3 поддерживаются и другие протоколы, что может быть актуально если CDN провайдер его не поддерживает. Так что это решение выглядит и более универсальным.

Так как для своего проекта я остановился на этом модуле, то приведу пример его настройки. Производится она в файле settings.php :

Еще один пример есть в документации к модулю Filebrowser.

Здесь нам понадобились имеющиеся у нас данные: "endpoint", "bucket", регион, синоним и пара ключ/секрет. Так же обратите внимание, что я задал дополнительный префикс metro2 , это просто корневая папка, чтобы не смешивать файлы от разных проектов.

Теперь s3 можно выбрать в качестве хранилища для файловых полей. Правильные URL к CDN файлам будут формироваться автоматически, без дополнительных модулей, а так как я указал еще и синоним, то и выглядеть они будут просто замечательно.

Обновление

Использование модуля показало, что механизм генерации стилей изображений работает очень медленно. Из-за этого странички после очистки кеша могут загружаться по 10 и даже более секунд, что, конечно же, неприемлемо.

Разработчики модуля в курсе проблемы и даже выпустили патч, который должен ее решить, но, к сожалению, в моем случае, особых улучшений не было.

Еще одна проблема — при генерации стилей изображений, файлы во временной папке, которые передавались потом в хранилище, не удалялись после закачки. А после очистки кеша добавлялись новые экземпляры. За пару дней работы сайта временная папка довольно прилично раздулась, и пока мне не удалось найти решение этой проблемы.

Перенос существующих файлов в CDN

Описанная выше конфигурация будет работать только для новых полей и новых загруженных в них файлов. Если же нужно изменить хранилище и перенести файлы для существующего поля, то штатными средствами это сделать не получится.

Закачать скачанные файлы в CDN так, чтобы путь соответствовал новому положению файлов, в моем случае — это metro2/images , где metro2 — дополнительный префикс, который я указал.

Не забудьте также указать правильные права доступа к файлам, если это публичные файлы, то доступ на чтение должен быть открыт всем.

Найти в базе данных, в таблице file_managed записи для нужных файлов и заменить им хранилище в поле uri на s3 . В моем случае исходным значением было public , и я переносил все файлы внутри папки images , поэтому просто сделал замену всем записям начинающимся с public://images :

Примечание

Для модуля S3 File System есть команда Drush s3fs-copy-local и кнопка в интерфейсе "Copy local public files to S3", которые позволяют автоматически перенести файлы в хранилище. Данная возможность работает только для конфигурации хранилища для всей папки локальных (и/или приватных) файлов.

Небольшая оптимизация

Подсмотрел в модуле CDN, что для более быстрой установки соединения с CDN можно добавить две директивы внутрь тега head :

Я это сделал внутри файла MYTHEME.theme в папке темы оформления:

Вот и все, на этом процесс настройки заканчивается.

Возможные проблемы

Может об этом стоило упомянуть раньше, но скорость работы Drupal c файлами в CDN существенно ниже, чем с локальными. Они дольше загружаются в поля, дольше генерируются стили изображений. Для каких-то проектов это может быть весьма существенно, но в моем случае файлы загружаются не пользователями, поэтому на них это никак не отражается. Просто имейте ввиду, что такой недостаток есть и, если это критично, то есть смысл рассмотреть другие варианты интеграции с Drupal или другие протоколы загрузки файлов в CDN.

Примечание

Описанная выше проблема относится к опыту использования модуля Flysystem. С модулем S3 File System такой проблемы нет.

Так как файлы в CDN располагаются на другом домене, то на них будут действовать более строгие политики взаимодействия с файлами. За это отвечает технология CORS (Cross-origin resource sharing), параметры которой могут быть частично настроены в панели управления Spaces, но на данный момент, возможности этих настроек выглядят весьма скромно. Хотя может я просто не разобрался как это правильно делать. В общем, тоже имейте это ввиду, если делаете какие-либо операции с файлами в своем коде.

Выводы

Я очень доволен проделанной работой и в будущем собираюсь применять данный подход для проектов, на которых имеются мало-мальски существенные объемы файлового контента.

Использование CDN — это один из способов повысить скорость загрузки сайта, и такая оптимизация определенно понравится пользователям, сделает интернет чуточку быстрее, а мир чуточку лучше!


Краткое описание: Позволяет пользователям закачивать и прикреплять файлы к материалам сайта.

Краткое описание (en): Allows users to upload and attach files to content.

Сведения об установке

Инструкция по установке: Установка модулей Drupal 6

Возможность прикрепления любых (хотя с оговорками) файлов к материалам дает еще один из дополнительных модулей ядра — Upload. Подключать его скорее всего вам не придется: обычно он включен уже при умолчанию вместе с самим Drupal’ом. Но если он все-таки не подключен — можете сделать это стандартным способом.

Как и с другими модулями, связанными с созданием контента сайта, вам прежде всего надо разобраться с тем, кому следует, а кому не следует использовать возможности модуля, для чего надо перейти на страницу: Управление → Управление пользователями → Разрешения (Administer → User management → Permissions). Соответствующих настроек, кстати, всего две: «загружать файлы» (upload files) и «смотреть загруженные файлы» (view uploaded files).

Далее — настройка самого модуля. Она находится по адресу: Управление → Настройка сайта → Загрузки файлов (Administer → Site configuration → File uploads). При стандартных модулях страница загрузки файлов состоит всего лишь из одного раздела и выглядит вот так:

Настройки загрузки файлов

Здесь все пояснено и стандартно. Если возражений нет — нажимайте на кнопку «Сохранить конфигурацию» (Save configuration) и приступайте непосредственно к добавлению файлов.

Правда, для этого надо сделать еще кое-что, а именно — разрешить добавление файлов для конкретных типов материалов. Скорее всего, это уже разрешено, а проверить это можно на обычной странице настройки типов материалов: Управление → Управление контентом → Типы материалов (Administer → Content management → Content types), где выбираете в таблице строку с нужным вам типом и нажимаете «изменить» (edit). На открывшейся странице раскрываете секцию «Процесс» (Workflow settings) и смотрите на опцию «Приложения». Если там стоит «Отключено» (Disabled) — переключайте на «Включено» (Enabled):

Настройка типа материалов

«Сохраняетесь» и можете спокойно приступать к созданию самих материалов с прикрепленными файлами. Это делается как обычно: Создать материал (Create content) → <Название типа материалов>. Здесь вы можете наблюдать небольшую секцию «Приложенные файлы» (File attachments), которая вам наверняка знакома по многим компьютерным программам или, скажем, по сервисам электронной почты:

Прикрпеление файлов к материалу

И тут есть что называется одно НО. Дело в том, что когда я начинал работать с Drupal’ом — обнаружилось, что не грузятся файлы, название которых на русском языке. Не знаю, решена ли эта проблема на данный момент, но лично я с тех пор предпочитаю все названия закачанных файлов (да и создаваемых тоже) давать исключительно латиницей. Что и вам советую.

Еще вы можете добавить файлы к уже существующим материалам своего сайта. Для этого вам надо уже созданную ноду найти в таблице содержимого сайта, куда можно попасть по адресу: Управление → Управление контентом → Содержимое (Administer → Content management → Content). Работа с уже имеющимися материалами ничем не отличается от работы с новыми.

По умолчанию в Друпал загружаемые файлы помещаются в папку sites/default/files и доступны для скачивания. Однако иногда возникает задача защитить некоторые файлы от скачивания или предоставить доступ к этим файлам для пользователей определенных ролей. Решению этой задачи и посвящена данная статья.

Указываем путь приватной файловой системы

Первым делом необходимо создать защищенную директорию, в которой будут храниться файлы, доступ к которым требуется ограничить. Для этого в разделе админки «Конфигурация – Файловая система» (admin/config/media/file-system) в поле «Приватный путь файловой системы» введем, например, адрес sites/default/files/private. После сохранения настроек Друпал создаст папку private в директории sites/default/files и защитит ее файлом .htaccess.

Теперь мы можем поместить какой-нибудь файл в папку sites/default/files/private. Введя путь к файлу в адресную строку браузера, мы получим ответ сервера «Доступ запрещен». Правда, как справедливо отмечается здесь, мы можем и не защитить таким образом файл от скачивания без дополнительных настроек веб-сервера. Поэтому правильнее помещать защищенную папку вне корневой директории сайта. Для этого в поле «Приватный путь файловой системы» вводим не sites/default/files/private , а ../private.

Итак, первая часть задачи решена – мы создали защищенную директорию, чтобы не допустить скачивания хранящихся в ней файлов по прямым ссылкам. Теперь нужно предоставить доступ к этому файлу только для пользователей определенной роли, например, администраторов сайта.

Используем hook_file_download() для управления доступом к приватным файлам

Пусть в одном из типов материалов сайта имеется поле «Файл», при этом загружаемые через это поле файлы должны быть доступны только администраторам сайта.

Для этого сначала в настройках данного поля в опции «Хранилище» указываем «Приватные файлы».

Далее создаем модуль, в котором имплементируем хук hook_file_download():

<?php
/**
* Implements hook_file_download().
*/
function MODULE_file_download ( $uri ) <
global $user ;
if ( in_array ( 'administrator' , $user -> roles ) ) <
return array ( 'Content-Type' => file_get_mimetype ( $uri ) ) ;
> else <
return - 1 ;
>
>

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

Форма обратной связи на Drupal Webform

Всем, аллоха! Сегодня пост будет про то, как в Drupal создавать формы обратной связи через Webform с возможностью прикрепления файлов. Казалось бы, «Ха, да очень просто!» , но я потратил на решение этой задачи неделю. Хотите знать почему? Тогда прошу к прочтению.

Началась вся эта история, когда меня попросили сделать сайт для одной компании. Решил делать сайт с душой, так как обратились ко мне хорошо знакомые люди. Описывать подробно, что это за сайт и как он разрабатывался, я сейчас не буду. Расскажу лишь про самую интересную задачу в рамках этого проекта, с которой я столкнулся – создание формы обратной связи для привлечения клиентов.

Согласитесь, что при обращении за услугами в любую компанию, вам, как правило, необходимо приложить к письму какие-либо документы. А эти документы в свою очередь могут содержать корпоративную или личную информацию, доступ к которой лучше оставлять ограниченным. Собственно после таких рассуждений я и составил список требований к «правильной» форме обратной связи:

  • Возможность загрузки произвольного количества файлов;
  • Управление списком доступных расширений файлов для загрузки;
  • Разграничение прав и управление доступом к загруженным файлам;
  • Отправка письма с прикрепленными файлами (а не ссылкой на них) на указанную почту при успешном заполнении формы.

В моем видении проекта должно быть так: после загрузки файлов доступ к ним имеют лишь пользователи с определенной ролью.

Элемент Webform для загрузки файлов

Идеальным визуальным решением для мультизагрузки файлов к форме мне тогда показался принцип работы File Field Widget в нодах: после каждого загруженного файла отображается форма для загрузки следующего. Собственно, так и получился модуль Webform Multiple File. Более подробно о модуле сможете прочитать по ссылке.

Мультизагрузка файлов к форме

Private file system для Webform

Надеюсь, для вас не секрет, что Drupal из коробки уже умеет разграничивать доступ к файлам. При работе с Private file system поднимается ядро Drupal и проверяются права (permissions) текущего пользователя перед тем, как отдать ему файл. Чтобы настроить эту систему:

  • Перейдите в admin / config / media / file - system и укажите путь к директории для хранения закрытых файлов. Например, у меня это будет sites / default / files / private . После сохранения настроек будет инициализирована директория "private" , закрытая от внешнего мира через .htaccess директивы.
  • К вашей Webform для обратной связи добавьте элемент ‘Multiple file’ и в настройках Upload destination выберите Private files . Также можете выбрать поддиректорию для хранения файлов, загруженных именно через данный элемент вебформы.

С данными настройками доступом к загруженным файлам будут обладать только те пользователи, роль которых позволяет просматривать результаты Webform. Другими словами, это права “Access all webform results” или “Access own webform results” на странице admin / people / permissions .

Если у вас появится желание более широко разграничить права для ролей, то хук hook_file_download ( ) вам в помощь. Ну и, возможно, потребуется поставить пару Breakpoint’ов для отладки в функции file_download ( ) – статья про отладку PHP приложений вам в помощь.

Отправка писем с прикрепленными файлами

По умолчанию Webform отсылает письмо, в котором предоставляются только ссылки на файлы. Я же решил, что это будет совершенно не практично, ведь письмо вероятнее всего будут пересылать из отдела в отдел компании. И что всей компании предоставлять административный доступ к сайту, чтобы выкачать несколько файлов? Разумеется, что нет. Поэтому загруженные файлы должны прикрепляться к письму.

Для решения этой задачи нам потребуется:

  • Установить контриб модуль Mail System;
  • Установить контриб модуль Mime Mail;
  • Имплементировать hook_mail_alter ( ) в своем модуле.

Указанные модули необходимо просто установить. Не помню, чтобы изменял настройки, но на всякий случай приложу конфигурацию Mail System.

Настройки модуля Mail System

Теперь необходимо перехватить письмо до того, как его Drupal отправит, и прикрепить к нему загруженные файлы. Код не претендует на изящность – это было быстрое и рабочее решение на момент написания проекта. Итак, в своем модуле имплементируем следующий хук:

Единственное, что требуется изменить в приведенном коде под конкретный проект – это константу MY_MODULE_WEBFORM_FILE_COMPONENT_NAME , храняющую машинное имя компонента Webform, через который загружаются файлы. Взять эти данные можно в настройках компонента – Field Key .

Ну вот, собственно, после данных манипуляций с настройками вы получаете удобную и безопасную форму контактов или оформления заявок. Еще могу посоветовать прикрутить к форме Google Analytics трекер, чтобы отслеживать конверсию.

Еще один важный момент : представленное решение является стабильным, проверенным и рабочим на случай, если у вас одна контактная форма (другими словами, одна нода типа Webform), которая содержит только один элемент Multiple File для загрузки файлов. Я просто хочу предупредить что, если у вас немного отличается структура проекта от моего, то существует вероятность появления ошибок. Паниковать и кричать «Ниработае. 1» не стоит – я уверен, проблема решится изменением нескольких строчек кода.

В случае появления вопросов или неразрешимых проблем при попытке воспроизвести данное решение на вашем проекте – обращайтесь. Ну и обсуждениям в комментариях я тоже буду рад!

Читайте также: