npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

easy-yandex-s3

v2.0.0

Published

Use Yandex S3 API to upload, list, download and remove files from Yandex Cloud service.

Downloads

3,145

Readme

Easy Yandex S3 Logo

Build Status YouTube IlyaDevman

Использовать S3 API Яндекс.Облака еще проще.
Хранилище называется у них там Object Storage.

✓ Загружайте файл
✓ Загружайте массив файлов
✓ Загружайте целые папки с вложенными внутри папками и файлами
✓ Загружайте Buffer
✓ Скачивайте файлы с бакета
✓ Удаляйте отдельные файлы с бакета
✓ Удаляйте все файлы бакета
✓ Получайте информацию о файлах в бакете

ℹ️ Внимание! Это версия 2.x

  • Она переписана на TypeScript и имеет .d.ts файлы.
  • Это не мешает использовать библиотеку в JavaScript проектах.

Для того, чтобы использовать старую стабильную версию библиотеки, реализованную на JavaScript:

npm i [email protected]

Поехали!

Оглавление

Ссылка на описание официального 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.

Доступ к бакету можно получить с помощью специального аккаунта, его называют сервисный аккаунт.

От него есть логин и пароль, только логин и пароль называется ключем, а логин - это "Идентификатор ключа", а пароль - это "Секретный ключ". Не бойтесь, здесь все очень легко.

И так, предположим вы уже сделали свой бакет (как его делать, я не рассказываю, там всё довольно просто). А может даже уже сделали папки внутри (кстати, это не обязательно).

Время получить доступ для работ с бакетом!

Создайте сервисный аккаунт в Яндекс.Облаке

  1. Зайдите в ЛК
    https://console.cloud.yandex.ru/cloud

  2. В каталогах выберите нужный каталог в списке справа.

  3. В меню слева нажмите Сервисные аккаунты

  4. Справа сверху нажмите Создать аккаунт

  5. Придумайте название аккаунту, оно вам не понадобится. Добавьте роли: iam.serviceAccounts.user, editor. Сохраняйте.

  6. Нажмите на сервисный аккаунт, чтобы открыть его.

  7. Справа сверху нажмите "Создать новый ключ" -> "Создать клч доступа"

  8. Придумайте описание. Создавайте.

  9. У вас появилось окошко с 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
});