/ php

Как работать с DigitalOcean Spaces в PHP

В предыдущей статье я тестировал хранилище DigitalOcean, где описал тонкости работы, достоинства и недостатки их сервисов. В этой статье я решил пойти дальше и описать пример работы по API с хранилищем, используя язык программирования PHP.

Если вы ещё не пользовались услугами Digital Ocean, то советую попробовать (уверен, вы не пожалеете). А при регистрации по инструкции из этой статьи, вы получите бонус в размере 100$ на оплату услуг.

Если вы ранее пользовались услугами облачного хранилища, Amazon S3, например, и писали код для работы с ним, то, можете заметить, что раpница между DigitalOcean Spaces и Amazon заключается только в конфигурационных параметрах при аутентификации. В остальном же, их принципы работы одинаковы, в результате чего, они являются полностью взаимозаменяемыми.

А это значит, что вы даже можете использовать готовый Amazon S3 клиент, подключаясь и работая с облачным хранилищем Digital Ocean Spaces. Для разработчиков Laravel вы можете просто использовать существующий драйвер S3 для Flysystem при подключении к DO Spaces.

Создание DigitalOcean spaces access key

Для начала, зарегистрируйтесь в DigitalOcean Spaces по инструкции и сгенерируйте ключ доступа, открыв страницу, и нажав на кнопку управления ключами manage_keys

Где в секции "Spaces access keys" нужно перейти в меню добавления нового ключа spaces_keys

Теперь осталось лишь как-то его назвать и подтвердить добавление ключа create_new

В итоге, будет создан ключ и секретный код, которые в дальнейшем понадобятся нам для работы с хранилищем по API
final

Как в PHP работать с DigitalOcean Spaces

Помните, что мы с вами обсуждали, что Digital Ocean Spaces является полностью совместимым и взаимозаменяемым с AWS PHP клиентами. Я продемонстрирую это на практике, и докажу, что это действительно так.

Итак, находим любой Github репозиторий с библиотекой, работающей Amazon AWS, который мы применим под лад работы с Digital Ocean Spaces.

В этом туториале я буду использовать популярную библиотеку для работы с AWS - Flysystem AWS SDK V3

Для начала, подключим эту библиотеку через composer:

composer require league/flysystem-aws-s3-v3

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

Загрузка приватного файла

Теперь создадим файл do-spaces.php в корне проекта, и добавим в него такое содержимое:

<?php

require __DIR__ . '/vendor/autoload.php';

use Aws\S3\S3Client;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\Filesystem;

// создание клиента работы с хранилищем
$client = new S3Client([
    'credentials' => [
        'key' => 'YOUR_key', // ключ с предыдущего шага
        'secret' => 'SECRET_KEY' // secret с предыдущего шага
    ],
    'region' => 'fra1', // регион сервера, выбранный во время создания хранилища
    'endpoint' => 'https://fra1.digitaloceanspaces.com', // строка, формирующаяся по принципу https://${REGION}.digitaloceanspaces.com
    'version' => 'latest',
]);

// вместо YOUR_BUCKET_NAME укажите имя своего хранилища 
$adapter = new AwsS3Adapter($client, 'YOUR_BUCKET_NAME');
$filesystem = new Filesystem($adapter);

// загрузка картинки на сервер
$imagePath = __DIR__ . '/example-image.png';
$imageName = basename($imagePath);

$stream = fopen($imagePath, 'r+');
$filesystem->writeStream("images/{$imageName}", $stream, ['visibility' => 'private']);

Посмотреть настройки своего хранилища вы можете на странице Spaces configs

И последнее, что осталось - добавить в корень проекта файл example-image.png, и проверить работу скрипта, выполнив:

php do-spaces.php

И, если всё было настроено правильно, файл должен был опубликоваться в облачном хранилище.
uploading_success

Но, загрузить приватный файл - то одно дело. А как теперь его прочитать? Для того, чтобы прочитать приватный файл, напишем такой код:

<?php
//...
// создание клиента работы с хранилищем
//$client = new S3Client([...]);

$command = $client->getCommand('GetObject',  [
    'Bucket' => 'YOUR_BUCKET_NAME', // вместо YOUR_BUCKET_NAME укажите имя своего хранилища 
    'Key'    => 'FILE_PATH' // путь к файлу, в моём случае - images/private2.png
]);

// выполняем команду на получение файла, и задаём срок действия ссылки 10 минут (т.е. через 10 минут ссылка перестанет работать)
$res = $client->createPresignedRequest($command, '+10 minutes');

$signedUrl = (string) $res->getUri();
echo $signedUrl;

В результате выполнения этого кода, мы должны увидеть ссылку, по которой будет доступен наш приватный файл
private-file

Загрузка общедоступных (публичных) файлов

Если мы перейдём по URL-адресу ранее загруженной картинки, то получим сообщение об ошибке, вроде этой access_errror

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

Для загрузки общедоступных файлов, модифицируем наш PHP-код:

// заменив строку 
$filesystem->writeStream("images/{$imageName}", $stream, ['visibility' => 'private']);

// на новую
$filesystem->writeStream("images/{$imageName}", $stream, ['visibility' => 'public']);

Перед выполнением нового запроса, удалите файл example-image.png с хранилища, который был загружен ранее.

Повторно выполнив скрипт, загрузим файл

php do-spaces.php

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

Резюме

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

Если вам интересно, как устроено API DigitalOcean Spaces внутри, то можете ознакомиться с их документацией по ссылке. И, если будет такое желание, можете реализовать свой собственный клиент для работы с хранилищем.