Как загрузить файл на Яндекс.Диск из 1С 7.7 через REST API?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

В этой статье разберем, как реализовать загрузку файлов на Яндекс.Диск непосредственно из 1С 7.7. Такая задача часто возникает, когда 1С работает на удаленном сервере, и нет возможности использовать стандартный клиент Яндекс.Диска для синхронизации папок. Мы будем использовать REST API Яндекса и COM-объекты для отправки HTTP-запросов.

Основная сложность, с которой сталкиваются разработчики, — это передача самого файла. Если получение URL для загрузки (первый шаг по документации Яндекса) обычно не вызывает проблем, то как прикрепить бинарные данные файла к PUT-запросу — не всегда очевидно. Рассмотрим эту задачу по шагам.

Анализ проблемы: как передать тело файла в PUT-запросе

Процесс загрузки файла на Яндекс.Диск через API состоит из двух этапов:

  1. Отправка GET-запроса на специальный адрес API, чтобы получить временную уникальную ссылку (URL) для загрузки файла.
  2. Отправка PUT-запроса с бинарными данными файла по полученной ссылке.

Автор исходного вопроса успешно справился с первым шагом, но остановился на втором. Его код получал URL, но не отправлял сам файл, потому что метод Send() вызывался без параметров.

Вот как выглядел проблемный участок кода:


... // Код получения ТехУрл (URL для загрузки)
httpobj.Open("PUT",ТехУрл,0);      
httpobj.Send(); // <-- Проблема здесь: файл не передается
Сообщить("4: "+httpobj.status+":"+httpobj.statusText);
...

Чтобы решить эту проблему, нужно прочитать файл в специальный объект, который может хранить бинарные данные, и передать этот объект в качестве параметра методу Send().

Решение: используем ADODB.Stream для чтения и отправки файла

Самый правильный и распространенный способ для работы с бинарными данными (такими как файлы) в среде Windows Scripting Host, доступной из 1С 7.7, — это использование COM-объекта ADODB.Stream. Этот объект позволяет читать содержимое файла в поток (stream) данных и затем передавать этот поток в теле HTTP-запроса.

Разберем по шагам, как это работает:

  1. Создаем объект ADODB.Stream. Он является частью библиотеки Microsoft ActiveX Data Objects.
  2. Устанавливаем тип потока. Для файлов нужно указать тип adTypeBinary, что соответствует значению 1.
  3. Открываем поток. Метод Open() подготавливает объект к работе.
  4. Загружаем файл в поток. Метод LoadFromFile(ПутьКФайлу) читает все содержимое файла в объект.
  5. Отправляем запрос. Передаем объект потока в метод Send(dataStream) нашего HTTP-клиента.

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


Процедура глЗагрузитьОбновитьФайлНаЯндексДиске(token, УрлКYandexDisk, overwrite, ПутьКФайлуДляЗагрузки) Экспорт
    // Этап 1: Получение URL для загрузки
    httpobj=CreateObject("winhttp.winhttprequest.5.1"); 
    httpobj.Open("GET",УрлКYandexDisk,0);
    httpobj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
    httpobj.setRequestHeader("Authorization","OAuth " + token); 
    httpobj.Send("");
    Сообщить("1: "+УрлКYandexDisk); // папка на Я.Диске, куда требуется закачка
    Сообщить("2: "+httpobj.status+":"+httpobj.statusText);
    
    // Простая обработка JSON-ответа для получения ссылки
    Текст=0;
    Текст=СоздатьОбъект("Текст");
    Текст=httpobj.ResponseText;
    Текст=СтрЗаменить(Текст,"{""href"":""h","h");
    ТехУрл=СтрЗаменить(Текст,"""}","");
    Сообщить("3: "+ТехУрл); //технический url для закачки на Я.Диск
    
    // Этап 2: Подготовка и отправка файла
    
    // Создаем и настраиваем объект ADODB.Stream
    dataStream = СоздатьОбъект("ADODB.Stream");
    dataStream.Type = 1; // Тип данных - бинарный
    dataStream.Open();
    dataStream.LoadFromFile(ПутьКФайлуДляЗагрузки);
    
    // Открываем PUT-запрос по полученному URL
    httpobj.Open("PUT",ТехУрл,0);
    // Устанавливаем заголовок, указывающий, что мы передаем бинарный поток
    httpobj.SetRequestHeader("Content-Type", "application/octet-stream");
    
    // Отправляем содержимое файла, передавая объект потока в метод Send
    httpobj.Send(dataStream);
    
    Сообщить("4: "+httpobj.status+":"+httpobj.statusText); // Успех - это 201 Created
    Сообщить("5: "+httpobj.ResponseText); // Ответ о результате закачки
    
    dataStream.Close(); // Закрываем поток
    httpobj=0;
КонецПроцедуры

Важные моменты в этом коде:

Альтернативный вариант с MSScriptControl

В обсуждении был предложен еще один рабочий вариант, использующий MSScriptControl.ScriptControl. Этот подход может быть полезен, если по какой-то причине прямая передача COM-объекта в метод Send() не срабатывает в вашей среде.

Идея в том, чтобы выполнить строку VBScript-кода, который и вызовет нужный метод. 1С передает свои объекты в окружение скрипта, а он уже выполняет операцию.


Функция глЗагрузитьНаВебДав(ФайлИсточник, ИмяКаталога, ИмяФайла) Экспорт
    x = СоздатьОбъект("Microsoft.XMLHTTP");
    // Этот пример для WebDAV, но суть та же
    x.Open("PUT","http://User:password@addresWebDav/" + ИмяКаталога + ИмяФайла,0);
    x.setRequestHeader("Accept", "*/*");
    x.setRequestHeader("Content-Type","application/binary");
    
    // Создаем объект для выполнения скриптов
    Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl");
    Скрипт.language = "vbscript";
    
    // Готовим поток с файлом
    Stream = СоздатьОбъект("ADODB.Stream");
    Stream.Mode = 3;
    Stream.Type = 1;
    Stream.Open();
    Stream.LoadFromFile(ФайлИсточник);
    
    // Передаем наши COM-объекты в среду выполнения скрипта
    Скрипт.AddObject("s", Stream);
    Скрипт.AddObject("x", x);
    
    // Выполняем код на VBScript, который читает поток и вызывает Send
    Скрипт.Eval("x.Send(s.Read())");
    
    Stream.Close();
    Возврат x.Status;
КонецФункции // ЗагрузитьНаВебДав

Этот метод немного сложнее, но является надежным запасным вариантом. Здесь используется метод Stream.Read(), который читает все содержимое потока и возвращает его, а результат уже передается в x.Send().

Важные дополнения

Как получить токен авторизации?

В коде используется переменная token. Это OAuth-токен, который необходим для авторизации ваших запросов к API Яндекса. Его нужно получить один раз вручную:

  1. Зарегистрируйте приложение на OAuth-сервере Яндекса.
  2. В настройках выберите платформу «Веб-сервисы» и предоставьте права на доступ к Диску, например, «Запись в любом месте на Диске» (yandex_disk_write).
  3. После создания приложения вы получите его ClientID.
  4. Сформируйте и откройте в браузере ссылку вида: https://oauth.yandex.ru/authorize?response_type=token&client_id=<ВАШ_ClientID>
  5. Разрешите доступ вашему приложению. На экране появится токен, который нужно скопировать и сохранить. Он действителен 1 год.

Этот токен вы и будете передавать в процедуру в качестве параметра token.

Обработка ошибок

Приведенный код для краткости не содержит проверок. В реальных задачах обязательно проверяйте код ответа сервера после каждого запроса.

Альтернатива REST API: протокол WebDAV

Яндекс.Диск также поддерживает протокол WebDAV, который позволяет работать с диском как с сетевой папкой через HTTP-запросы. Этот подход может быть проще, так как не требует первого шага с получением временной ссылки.

Пример кода из сообщения №4 как раз демонстрирует работу по этому протоколу. Это отличная альтернатива для упрощения кода.

← На главную