Если вы не слышали ранее об Открытом Пакете Интеграций (что вполне вероятно), то небольшая вводная часть ниже, под катом. Для тех, кто уже знаком с ОПИ, данный раздел можно пропустить.
Открытый Пакет Интеграций (ОПИ) - это open-source набор методов для простой и быстрой интеграции с различными популярными API. Он состоит из аналогичных по функционалу 1С-расширения (CFE), OS-пакета и программы для Windows и Linux, которые предоставляют готовые функции для работы с целым набором различных онлайн-сервисов.
- ОПИ бесплатен и имеет открытый исходный код на GitHub. Вы всегда можете получить последнюю версию библиотеки на странице репозитория, а подписавшись - узнавать о выходе обновлений. Все релизы сопровождаются статьями на Инфостарт и разделами единой документации. На Инфостарт вы можете подписаться уже хоть сейчас, а про документацию я расскажу далее.
- Удобная единая документация. Она расположена на сайте opi.neocities.org и содержит в себе всю информацию, необходимую для работы: инструкции по предварительным действиям для начала интеграции, описания всех методов с параметрами и возвращаемыми значениями, примеры кода и т.д. Каждый API имеет там свой раздел.
- Простая установка. ОПИ распространяется во множестве вариантах: как XML файлы расширения, как EDT проект расширения, как файл расширения формата .cfe (версия 1С 8.3.9), как файл пакета для OneScript и еще в целом наборе пакетов и файлов для Windows и Linux. Из этого набора вы всегда сможете выбрать тот способ установки, который лучше подойдет для вашей конкретной задачи
На момент последнего обновления данной статьи, доступны следующие API:
Наиболее актуальную информацию можно посмотреть в репозитории или на вводной странице документации.
Яндекс Диск
Яндекс Диск - облачное хранилище от Яндекса. Я думаю все о нем слышали. Как и у большинства подобных ему облачных хранилищ, Диск предоставляет возможность управлять файлами и каталогами посредством API. Что и реализовано в сегодняшнем обновлении
Вот полный список доступных действий. Каждое действие - 1 функция:
- Функции для работы с файлами и папками
- Получить информацию о диске
- Получить список файлов диска
- Создать папку
- Загрузить файл (из Двоичных данных или по пути к файлу)
- Загрузить файл по URL на диск
- Получить информацию об объекте по его пути на Диске
- Создать копию объекта
- Переместить объект
- Удалить объект
- Получить ссылку на скачивание
- Функции для работы с объектами в публичном доступе
- Опубликовать объект в публичный доступ
- Получить информацию о публичном объекте по URL
- Получить ссылку для скачивания публичного объекта
- Сохранить публичный объект на свой диск Диск
- Получить список своих публичных объектов
- Отменить публикацию объекта
Описания методов и параметров, а также примеры кода можно найти в документации
Там же есть и инструкция получения Токена авторизации. С картинками.
Пример использования
Для демонстрации практического применения библиотеки мы с вами сейчас создадим простейший файловый менеджер для нашего Диска - в виде обработки. Он не будет претендовать на статус готового решения, но будет вполне работоспособен и наглядно покажет способы работы с API через библиотеку.
Это информация есть и в документации Открытого пакета интеграций
1. Перейдите на страницу создания приложения
2. Введите название сервиса, выберите Веб-сервисы в качестве платформы. Redirect URI можно указать любой или выбрать пункт Подставить URL для отладки - для работы с библиотекой он не понадобится.
3. В поле Доступ к данным добавьте разрешения как на скриншоте ниже, после чего нажмите Создать приложение
4. Сохраните ClientID и Client secret со страницы приложения
- Вызовите функцию OPI_YandexID.ПолучитьКодПодтверждения(), передав ClientID в качестве параметра. Она вернет ответ сервера Yandex, где будут поля
- user_code - необходимо будет ввести в браузере
- device_code - необходимо будет передать в другую функцию
- verification_url - URL, который нужно открыть в браузере
// Результат функции ПолучитьКодПодтверждения(), если перевести его в JSON
{
"verification_url": "https://ya.ru/device",
"user_code": "gjehyruw",
"interval": 5,
"expires_in": 300,
"device_code": "12207cafec1b40ad8d0052af3faf0d12"
}
6. Откройте URL из verification_url в барузере. Скорее всего это будет https://ya.ru/device. В появившееся поле введите user_code из пункта 5
7. После ввода кода в пункте 6, вызовите функцию OPI_YandexID.ПреобразоватьКодВТокен(), передав туда ClientID и ClientSecret из пункта 4, а также device_code из пункта 5. Сохраните полученные acess_token и refresh_token
// Результат функции ПреобразоватьКодВТокен(), если перевести его в JSON
{
"token_type": "bearer",
"refresh_token": "1:Tj6nD2vgE2L8jwSm:YgWjQXPv6_y3e07GW70ig2AOyEXoRVsKKpApGHq2EOg7pfx0MKrXiCrfLBFtzgQawdawdwadad3Sasa9z2H0vSeZKNmZmA",
"expires_in": 31535956,
"access_token": "y0_AgAAAABWxxdkAAs0QgAAAAD59cawdawdwadadVKIiwGK__crw"
}
acess_token используется во всех остальных функциях библиотеки, а при помощи refresh_token его можно обновить, когда срок жизни будет подходить к концу (при помощи функции OPI_YandexID.ОбновитьТокен())
Начнем наш менеджер с дерева файлов. Я создал реквизит формы типа Дерево с полями Имя, ПолныйПуть и ЭтоКаталог. И еще, отдельно, строковый реквизит для хранения Токена
Теперь это дерево необходимо заполнить файлами. Функция получилась довольно сумбурная - возможно, стоило разбить ее на подфункции, но я подумал, что так потеряется наглядность. Поэтому просто прокомментировал, что в ней происходит:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Токен = "y0_AgAAAABdylaOAAs0QgAAAAD5...";
СобратьДерево();
КонецПроцедуры
&НаСервере
Процедура СобратьДерево(Отступ = 0)
//Очищаем дерево
Если Отступ = 0 Тогда
ДеревоФайлов.ПолучитьЭлементы().Очистить();
КонецЕсли;
// Максимальное количество файлов, которые API может возвращать за 1 раз
МаксимумЭлементов = 20;
// Получаем ответ сервера типа Соответствие функцией из библиотеки
Результат = OPI_YandexDisk.ПолучитьСписокФайлов(Токен, МаксимумЭлементов, Отступ);
// Массив Файлов из ответа
Файлы = Результат["items"];
// Разбираем каждый файл
Для Каждого ФайлДиска Из Файлы Цикл
ПутьСтрока = СтрЗаменить(ФайлДиска["path"], "disk:", ""); // Каждый путь начинается с "disk:", который нам не нужен
ПутьМассив = СтрРазделить(ПутьСтрока, "/", Ложь); // Разбиваем путь типа /Папка/Папка/Файл в массив элементов по /
Счетчик = 0; // Для определения текущего индекса массив
ТекущийПуть = ""; // Проходя по массиву элементов пути мы будем собирать его обратно
ЭлементыТекущегоУровня = ДеревоФайлов.ПолучитьЭлементы(); // и повышать уровень дерева: /Папка - 1 Уровень /Папка/Папка - 2 уровень и т.д.
Для Каждого ЭлементПути Из ПутьМассив Цикл // Обходим каждый элемент пути
ТекущийПуть = ТекущийПуть + "/" + ЭлементПути; // Определяем текущий полный путь, прибавляя к прошлому пути текущее расположение
// было /Папка, стало /Папка/Папка
Если Счетчик = ПутьМассив.ВГраница() Тогда // В конце пути всегда файл. Т.е. если это - конец пути, то уровней больше не будет
НовыйЭлемент = ЭлементыТекущегоУровня.Добавить(); // Добавляем элемент файла в дерево
НовыйЭлемент.Имя = ЭлементПути;
НовыйЭлемент.ПолныйПуть = ТекущийПуть;
НовыйЭлемент.ЭтоКаталог = Ложь;
Иначе // Если это не последний элемент пути - это не файл, а каталог
Существует = Ложь; // Проверяем существование каталога. Ведь он уже мог быть добавлен
Для Каждого ЭлементУровня Из ЭлементыТекущегоУровня Цикл // с другим файлом
Если ЭлементУровня.ПолныйПуть = ТекущийПуть Тогда // Если каталог найден, т.е. уже был добавлен в дерево ранее
Существует = Истина; // ставим отметку
ЭлементыТекущегоУровня = ЭлементУровня.ПолучитьЭлементы(); // и определяем текущий уровень дерева - этот элемент будет родителем
КонецЕсли; // при слудующей иттерации
КонецЦикла;
Если Не Существует Тогда // Если же каталог не был добавлен ранее (и,собственно, не был найден)
// Добавляем его в дерево и определяем как текущий уровень - как родителя
НовыйЭлемент = ЭлементыТекущегоУровня.Добавить(); // следующего элемента в следующей иттерации цикла
НовыйЭлемент.Имя = ЭлементПути;
НовыйЭлемент.ПолныйПуть = ТекущийПуть;
НовыйЭлемент.ЭтоКаталог = Истина;
ЭлементыТекущегоУровня = НовыйЭлемент.ПолучитьЭлементы();
КонецЕсли;
КонецЕсли;
Счетчик = Счетчик + 1;
КонецЦикла;
КонецЦикла;
Если Не Файлы.Количество() = 0 Тогда // Рекурсивно вызываем эту функцию, добавляя к отступу от начала 20
СобратьДерево(Отступ + МаксимумЭлементов); // (максимальное количество получаемых за раз элементов)
КонецЕсли; // пока сервер не перестанет возвращать элементы
КонецПроцедуры
Для проверки я наделал в своем Диске различных вложенных папок. Структура построилась правильно
Теперь нужно добавить каких-нибудь функций. Начнем с перемещение файла - реализовать его можно при помощи события Перетаскивание элемента дерева.
&НаКлиенте
Процедура ДеревоФайловПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
ЭлементыПеретаскивания = ПараметрыПеретаскивания.Значение; // Массив идентиф. перемещаемых элементов
НовыйРодитель = ДеревоФайлов.НайтиПоИдентификатору(Строка); // Новый родитель перемещаемых объектов
СоответствиеПеремещения = Новый Соответствие; // Соответствие старого и нового пути для API
Если Не НовыйРодитель.ЭтоКаталог Тогда // Проверка перемещения в каталог
Сообщить("Перемещение возможно только в каталог"); // а не в другой файл
СобратьДерево();
Возврат;
КонецЕсли;
Для Каждого ЭлементПеретаскивания Из ЭлементыПеретаскивания Цикл
Текущий = ДеревоФайлов.НайтиПоИдентификатору(ЭлементПеретаскивания); //Получаем перемещаемый эл.
СтарыйПуть = Текущий.ПолныйПуть; //Путь до перемещения
Имя = Текущий.Имя;
НовыйПуть = НовыйРодитель.ПолныйПуть + "/" + Имя; //Путь после перемещения
Текущий.ПолныйПуть = НовыйПуть; //Записываем новый путь в ДЗ
СоответствиеПеремещения.Вставить(СтарыйПуть, НовыйПуть);
КонецЦикла;
ПереместитьОбъектыНаДиске(СоответствиеПеремещения); // Перемещаем объекты на самом диске
КонецПроцедуры
&НаСервере
Процедура ПереместитьОбъектыНаДиске(Знач СоответствиеПеремещения)
Для Каждого ЭлПеремещения Из СоответствиеПеремещения Цикл
//Перемещаем из старого пути (ключ) в новый (значение)
OPI_YandexDisk.ПереместитьОбъект(Токен, ЭлПеремещения.Ключ, ЭлПеремещения.Значение);
КонецЦикла;
КонецПроцедуры
Теперь при перетаскивании одной строки дерева в другую, файлы на диске также будут перемещаться. Для этого мы получаем старый и новый путь расположения файла и передаем их в функцию OPI_YandexDisk.ПереместитьОбъект().
Попробуем переместить картинку Море из корня во Вложенную тестовую папку
Все получилось. Далее не помешает возможность загружать на диск локальные файлы. Вызов выбора файла повесим на кнопку, а путь для сохранения будем определять по текущему элементу дерева значений.
&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
ТД = Элементы.ДеревоФайлов.ТекущиеДанные;
Если ТД = Неопределено Тогда // Путь загрузки определяется по текущему элементу дерева
Сообщить("Выберите назначение в дереве");
КонецЕсли;
Если Не ТД.ЭтоКаталог Тогда
ТД = ТД.ПолучитьРодителя(); // Если текущий элемент - не каталог, то берем родителя
КонецЕсли;
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
// Передаем родителя в доп. параметры
ОповещениеЗавершения = Новый ОписаниеОповещения("ПриВыбореФайла", ЭтотОбъект, ТД);
Диалог.МножественныйВыбор = Ложь;
Диалог.Показать(ОповещениеЗавершения);
КонецПроцедуры
&НаКлиенте
Процедура ПриВыбореФайла(ВыбранныйФайл, ДополнительныеПараметры) Экспорт
Если ВыбранныйФайл = Неопределено Тогда
Возврат;
КонецЕсли;
Если ДополнительныеПараметры = Неопределено Тогда
ПолныйПуть = "";
ДополнительныеПараметры = ДеревоФайлов;
Иначе
ПолныйПуть = ДополнительныеПараметры.ПолныйПуть;
КонецЕсли;
ПутьКФайлу = ВыбранныйФайл[0];
ФайлПути = Новый Файл(ПутьКФайлу);
ПутьЗагрузки = ПолныйПуть + "/" + ФайлПути.Имя; // Формируем путь на Диске
ЗагрузитьФайлНаДиск(ФайлПути.ПолноеИмя, ПутьЗагрузки);
НовыйЭлемент = ДополнительныеПараметры.ПолучитьЭлементы().Добавить(); // Добавляем новый файл в дерево
НовыйЭлемент.Имя = ФайлПути.Имя;
НовыйЭлемент.ПолныйПуть = ПутьЗагрузки;
НовыйЭлемент.ЭтоКаталог = Ложь;
КонецПроцедуры
&НаСервере
Процедура ЗагрузитьФайлНаДиск(Знач Файл, Знач Путь)
OPI_YandexDisk.ЗагрузитьФайл(Токен, Путь, Файл);
КонецПроцедуры
Попробуем загрузить сам файл нашей обработки во Вторую вложенную тестовую папку
Как вы уже могли заметить, большую часть времени при написании кода мы тратим на интерфейс, но не на работу с API Яндекса. Добавим еще две очень простые функции - удаление объекта и загрузку файла из облака на компьютер.
Удаление реализуется очень легко при помощи события ПередУдалением
&НаКлиенте
Процедура ДеревоФайловПередУдалением(Элемент, Отказ)
УдалитьФайл(Элемент.ТекущиеДанные.ПолныйПуть);
КонецПроцедуры
&НаСервере
Процедура УдалитьФайл(Знач Путь)
OPI_YandexDisk.УдалитьОбъект(Токен, Путь);
КонецПроцедуры
По умолчанию файлы удаляются в корзину, но вы можете удалять их сразу и навсегда при помощи последнего параметра функции OPI_YandexDisk.УдалитьОбъект(Токен, Путь, ВКорзину)
Теперь сохранение на компьютер. В нем тоже ничего сложного нет - надо скопировать и немного подправить диалог выбора файла из загрузки, чтобы он стал диалогом выбора каталога, а потом - создать небольшую процедуру уже непосредственно для сохранения.
&НаКлиенте
Процедура СохранитьФайл(Команда)
ТД = Элементы.ДеревоФайлов.ТекущиеДанные;
Если ТД = Неопределено Тогда // Путь загрузки определяется по текущему элементу дерева
Сообщить("Выберите назначение в дереве");
КонецЕсли;
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
// Передаем путь в доп. параметры
ОповещениеЗавершения = Новый ОписаниеОповещения("ПриВыбореКаталога", ЭтотОбъект, ТД.ПолныйПуть);
Диалог.МножественныйВыбор = Ложь;
Диалог.Показать(ОповещениеЗавершения);
КонецПроцедуры
&НаКлиенте
Процедура ПриВыбореКаталога(ВыбранныйКаталог, ДополнительныеПараметры) Экспорт
Если ВыбранныйКаталог = Неопределено Тогда
Возврат;
КонецЕсли;
ПутьККаталогу = ВыбранныйКаталог[0];
СохранитьФайлЛокально(ДополнительныеПараметры, ПутьККаталогу);
КонецПроцедуры
&НаСервере
Процедура СохранитьФайлЛокально(Знач ПутьДиска, Знач ПутьЛокальный)
МассивПути = СтрРазделить(ПутьДиска, "/");
ИмяФайлаДиска = МассивПути[МассивПути.ВГраница()];
ИмяФайлаДиска = ?(СтрНайти(ИмяФайлаДиска, ".") > 0, ИмяФайлаДиска, ИмяФайлаДиска + ".zip"); //Если сохраняем папку - добавляем .zip
Ответ = OPI_YandexDisk.ПолучитьСсылкуДляСкачивания(Токен, ПутьДиска); // Получем URL для скачивания
URL = Ответ["href"];
Ответ = OPI_Инструменты.Get(URL); // Получаем сам файл
Если ТипЗнч(Ответ) = Тип("ДвоичныеДанные") Тогда
Ответ.Записать(ПутьЛокальный + "\" + ИмяФайлаДиска); // Сохраняем на компьютер ПутьЛокальный + "\" + ИмяФайлаДиска
КонецЕсли;
КонецПроцедуры
Мы можем сохранять как файлы, так и папки. При сохранении папки она загружается как zip архив.
Готово!
Вот так, использовав 5 пластиковых бутылок и суперклей библиотеку и 15 минут времени мы сделали свой небольшой файловый менеджер для облака.
Он, конечно, не идеален и не обладает полным функционалом, но для показа библиотеки - самое то. Весь код обработки уместился в 246 строк - можете скачать epf в релизах (должно быть подключено расширение библиотеки, которое есть там же). Ссылка есть ниже.
Спасибо за внимание!
Репозиторий ОПИ: github.com/Bayselonarrend/OpenIntegrations
Последний релиз: github.com/Bayselonarrend/OpenIntegrations/releases/latest
Другие статьи про Открытый пакет интеграций на Инфостарт:
Мой GitHub: https://gitub.com/Bayselonarrend Лицензия MIT: https://mit-license.org