Использовать S3 API Яндекс.Облака еще проще.
Хранилище называется у них там Object Storage.
✓ Загружайте файл
✓ Загружайте массив файлов
✓ Загружайте целые папки с вложенными внутри папками и файлами
✓ Загружайте Buffer
✓ Скачивайте файлы с бакета
✓ Удаляйте отдельные файлы с бакета
✓ Удаляйте все файлы бакета
✓ Получайте информацию о файлах в бакете
- Она переписана на TypeScript и имеет .d.ts файлы.
- Это не мешает использовать библиотеку в JavaScript проектах.
Для того, чтобы использовать старую стабильную версию библиотеки, реализованную на JavaScript:
npm i easy-yandex-s3@1.1.8
Поехали!
Оглавление
- Теория - что такое хранилище и как работает
- Инструкция создания сервисного аккаунта
- Начало работы
- Примеры использования
- Разработчик @powerdot
- Разработчик @nukuutos
Ссылка на описание официального API Яндекса.
https://cloud.yandex.ru/docs/storage/s3/
Ссылка на описание S3 API Amazon (англ.)
https://docs.aws.amazon.com/en_us/AmazonS3/latest/API/Welcome.html
Теория O'RLY
Хранилище состоит из бакетов.
Бакет (Bucket) - это, грубо говоря, ваш жесткий диск в интернетах.
Чтобы загружать что-либо в Яндекс.Облако и хранить там свои файлы, вам нужно сделать этот самый бакет.
У бакета есть ID. ID совпадает с его названием, которое вы придумаете, например my-storage.
Доступ к бакету можно получить с помощью специального аккаунта, его называют сервисный аккаунт.
От него есть логин и пароль, только логин и пароль называется ключем, а логин - это "Идентификатор ключа", а пароль - это "Секретный ключ". Не бойтесь, здесь все очень легко.
И так, предположим вы уже сделали свой бакет (как его делать, я не рассказываю, там всё довольно просто). А может даже уже сделали папки внутри (кстати, это не обязательно).
Время получить доступ для работ с бакетом!
Создайте сервисный аккаунт в Яндекс.Облаке
-
Зайдите в ЛК
https://console.cloud.yandex.ru/cloud -
В каталогах выберите нужный каталог в списке справа.
-
В меню слева нажмите Сервисные аккаунты
-
Справа сверху нажмите Создать аккаунт
-
Придумайте название аккаунту, оно вам не понадобится. Добавьте роли: iam.serviceAccounts.user, editor. Сохраняйте.
-
Нажмите на сервисный аккаунт, чтобы открыть его.
-
Справа сверху нажмите "Создать новый ключ" -> "Создать клч доступа"
-
Придумайте описание. Создавайте.
-
У вас появилось окошко с 2мя ключами. Скопируйте их куда-нибудь, потому что секретный ключ выдается 1 раз в этой связке. Больше вы его не увидите.
Теперь у вас есть Идентификатор ключа (accessKeyId) и Секретный ключ (secretAccessKey), поздравляю, от души.
Как с этим работать
Установите npm-модуль в директории вашего проекта, это очень просто.
npm i easy-yandex-s3
Инициализируем работу с бакетом.
// Подключаем модуль
let EasyYandexS3 = require('easy-yandex-s3').default;
^ default — обязательно
// Инициализация
let s3 = new EasyYandexS3({
auth: {
accessKeyId: 'ИДЕНТИФИКАТОР_КЛЮЧА',
secretAccessKey: 'ДЛИННЫЙ_СЕКРЕТНЫЙ_КЛЮЧ',
},
Bucket: 'НАЗВАНИЕ_БАКЕТА', // например, "my-storage",
debug: true, // Дебаг в консоли, потом можете удалить в релизе
});
Загрузка файла в бакет
Общая конструкция:
.Upload(
{ параметры },
"папка/в/бакете"
)
- Загрузка по расположению файла
123.png -> [bucket-name]/test/d20e9d31-8eab-4618-aa1d-12dedc794356.png
let upload = await s3.Upload(
{
path: path.resolve(__dirname, './123.png'),
},
'/test/'
);
console.log(upload); // <- Возвращает путь к файлу в хранилище и всякую дополнительную информацию.
// если вернулся false - произошла ошибка
// Файл загрузится в [my-stogare]/test/{uuid-v4}.{расширение}
- Загрузка по расположению файла, с указанием оригинального имени и расширения файла
123.png -> [bucket-name]/test/123.png
let upload = await s3.Upload(
{
path: path.resolve(__dirname, './123.png'),
save_name: true,
},
'/test/'
);
console.log(upload); // Возвращает путь к файлу в хранилище и всякую дополнительную информацию.
// если вернулся false - произошла ошибка
// Файл загрузится в [my-stogare]/test/123.png
- Загрузка по расположению файла, с указанием имени файла для загрузки
123.png -> [bucket-name]/test/lolkek.png
let upload = await s3.Upload(
{
path: path.resolve(__dirname, './123.png'),
name: 'lolkek.png',
},
'/test/'
);
console.log(upload); // <- Возвращает путь к файлу в хранилище и всякую дополнительную информацию.
// если вернулся false - произошла ошибка
// Файл загрузится в [my-stogare]/test/lolkek.png
- Загрузка буфера
-> [bucket-name]/test/d20e9d31-8eab-4618-aa1d-12dedc794356.png
let upload = await s3.Upload(
{
buffer: file_buffer,
},
'/test/'
);
console.log(upload); // <- Возвращает путь к файлу в хранилище и всякую дополнительную информацию.
// если вернулся false - произошла ошибка
// Файл загрузится в [my-stogare]/test/{uuid-v4}.{расширение}
- Загрузка буфера с определением имени и расширения файла
-> [bucket-name]/test/lolkek.png
let upload = await s3.Upload(
{
buffer: file_buffer,
name: 'lolkek.png',
},
'/test/'
);
console.log(upload); // <- Возвращает путь к файлу в хранилище и всякую дополнительную информацию.
// если вернулся false - произошла ошибка
// Файл загрузится в [my-stogare]/test/lolkek.png
return:
{
ETag: '"md5sum"',
VersionId: 'null',
Location:
'https://actid-storage.storage.yandexcloud.net/test1/name.png',
key: 'test1/name.png',
Key: 'test1/name.png',
Bucket: 'actid-storage'
}
Загрузка файлов в бакет
- Загружаем контент папки в бакет
контент папки -> [bucket]/folder_on_server/
Модуль берет все файлы и папки внутри указанной папки. То есть саму папку он не загрузит, а только ее контент.
Представим себе папку ./my_folder
:
- my_folder
-
- 1.png
-
- 2.png
-
- folder_inside
-
-
- 3.png
-
Устанавливаем параметр route
как "folder_on_server", грубо говоря, это [my_bucket]/folder_on_server/
То загрузка на бакет будет следующей:
[my_bucket]/folder_on_server/1.png
[my_bucket]/folder_on_server/2.png
[my_bucket]/folder_on_server/folder_inside/3.png
Грубо говоря, мы просто телепортируем контент указанный папки в указанную папку на сервере.
Ребят, это просто CMD+C CMD+V.
// Относительный путь:
let upload = await s3.Upload(
{
path: './my_folder', // относительный путь до папки
save_name: true, // сохранять оригинальные названия файлов
},
'/folder_on_server/'
);
console.log(upload); // <- массив загруженных файлов
// Игнорируем файлы и папки внутри:
let upload = await s3.Upload(
{
path: './my_folder', // относительный путь до папки
save_name: true, // сохранять оригинальные названия файлов
ignore: ['.git', '/assets/video'], // игнорируем все файлы .git и путь внутри с файлами /assets/video
},
'/folder_on_server/'
);
console.log(upload); // <- массив загруженных файлов
// Прямой путь:
let upload = await s3.Upload(
{
path: '/Users/powerdot/sites/example.com/', // прямой путь до папки
save_name: true, // сохранять оригинальные названия файлов
},
'/folder_on_server/'
);
console.log(upload); // <- массив загруженных файлов
- Загрузка нескольких файлов
массив файлов -> [bucket]/folder_on_server/
// используем массив файлов следующим образом:
let upload = await s3.Upload(
[
{ path: './file1.jpg', save_name: true }, // относительный путь до файла с сохранением имени
{ path: '/Users/powerodt/dev/sites/folder/file2.css' }, // прямой путь до файла с изменением имени на uuid-v4
{ path: './file.html', name: 'index.html' }, // относительный путь на файл с изменением имени при загрузке на index.html
],
'/folder_on_server/'
);
return:
Массив из Upload-объектов
[
{
ETag: '"md5sum"',
VersionId: 'null',
Location:
'https://actid-storage.storage.yandexcloud.net/test1/name.png',
key: 'test1/name.png',
Key: 'test1/name.png',
Bucket: 'actid-storage'
},
...
]
Получение списка директорий и файлов бакета
Общая конструкция:
.GetList(
"директория/бакета"
);
- Получение корня бакета
let list = await s3.GetList();
- Получение списка директорий и файлов из конкретной директории
let list = await s3.GetList('/test/');
-
Contents
- содержит список файлов, содержащихся в папкеtest
-
CommonPrefixes
- содержит список папок, содержащихся в папкеtest
return:
{
IsTruncated: false,
Contents: [
{
Key: 'eys3-testing/file1.rtf',
LastModified: new Date("2022-08-24T01:55:02.431Z"),
ETag: '"ee4e1fb1ab82ee0a650d8e4a8c274d9b"',
ChecksumAlgorithm: [],
Size: 413,
StorageClass: 'STANDARD',
Owner: [Object]
},
{
Key: 'eys3-testing/file2.rtf',
LastModified: new Date("2022-08-24T01:55:02.483Z"),
ETag: '"ee4e1fb1ab82ee0a650d8e4a8c274d9b"',
ChecksumAlgorithm: [],
Size: 413,
StorageClass: 'STANDARD',
Owner: [Object]
}
],
Name: 's3library',
Prefix: 'eys3-testing/',
Delimiter: '/',
MaxKeys: 1000,
CommonPrefixes: [ { Prefix: 'eys3-testing/folder1/' } ],
KeyCount: 3
}
Скачивание файла из бакета
Общая конструкция:
.Download(
"путь/до/файла/в/бакете",
"путь/куда/сохраняем/на/клиенте"
);
- Скачивание файла и получение буфера этого файла
let download = await s3.Download('test/123.png');
- Скачивание файла и сохранение его в файл
let download = await s3.Download('test/123.png', './myfile.png');
// в download так же дополнительно вернется Buffer
// а полученный файл с бакета будет сохранен как myfile.png в директории выполнения скрипта
return:
{
data: {
AcceptRanges: "bytes",
LastModified: new Date("2019-07-15T22:10:09.000Z"),
ContentLength: 20705,
ETag: '"md5sum"',
ContentType: "application/octet-stream",
Metadata: {},
Body: Buffer.from("250001000192CD0000002F6D6E742F72", "hex"),
},
destinationFullPath: false,
fileReplaced: false,
};
Удаление файла из бакета
Общая конструкция:
.Remove(
"/путь до файла в бакете/"
);
- Удаляем файл
let remove = await s3.Remove('test/123.png');
// возвращается true или false.
// true при успешном удалении, даже если файла нет
// false при других критических ошибках
return:
true;
Удаление всех файлов из бакета
Общая инструкция:
.CleanUp()
Очищаем бакет от файлов целиком и полностью:
let result = await s3.CleanUp();
Технически файлы удаляются пачками по 1000 штук. Для каждой пачки будут свои Deleted
и Errors
ключи, которые содержат данные об успешно удалённых объектах(файлах) и данные о файлах, при удалении которых возникла ошибка.
return:
// Успешно удаленно 3 объекта
[ { Deleted: [ [Object], [Object], [Object] ], Errors: [] } ]
// Что из себя представляет Object.
{ Key: '/путь/до/файла', VersionId: 'null' }
// При неуспешном выполнении метода будет получен следующий результат:
false
Примеры использования
Multer и Express
Пример загрузки файлов через multer и express.
Кейс: нужно загрузить файл с фронта на сервер, а потом загрузить его на Yandex Object Storage.
- Устанавливаешь express и multer
npm i express
npm i multer
- В файле проекта привязываешь multer и easy-yandex-s3
// Создаем веб-сервер
let express = require('express');
let app = express();
app.listen(8000);
// Подключаем multer и eys3
let multer = require('multer');
let EasyYandexS3 = require('easy-yandex-s3').default;
// Указываем аутентификацию в Yandex Object Storage
let s3 = new EasyYandexS3({
auth: {
accessKeyId: '',
secretAccessKey: '',
},
Bucket: 'my-storage', // Название бакета
debug: false, // Дебаг в консоли
});
// Подключаешь мидлвар multer для чтения загруженных файлов
app.use(multer().any());
// Делаешь фетч post-запроса с отправленным файлом по ссылке /uploadFile
app.post('/uploadFile', async (req, res) => {
let buffer = req.files[0].buffer; // Буфер загруженного файла
let upload = await s3.Upload({ buffer }, '/files/'); // Загрузка в бакет
res.send(upload); // Ответ сервера - ответ от Yandex Object Storage
});