Как программно загрузить картинки из интернета по ссылке в 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Торговля и дистрибуция
← На главную

Загрузка изображений из интернета по прямой ссылке, особенно если требуется поддержка защищенного протокола HTTPS, является частой задачей при интеграции 1С с внешними системами или веб-сайтами. В этом материале мы подробно рассмотрим различные подходы и примеры кода для решения этой проблемы, ориентируясь на типовые механизмы платформы 1С:Предприятие.

Существует несколько способов программной загрузки файлов из интернета в 1С. Мы разберем два основных подхода: использование метода КопироватьФайл и более универсальный метод с применением объектов HTTPСоединение и HTTPЗапрос. Также уделим внимание аспектам работы с защищенными соединениями, обработке ответов сервера и сохранению файлов в информационной базе.

Метод 1: Использование функции КопироватьФайл

Функция КопироватьФайл(откуда, куда) является одним из самых простых способов копирования файлов. Она поддерживает работу с сетевыми адресами, включая схемы HTTP, HTTPS и FTP. Это означает, что вы можете указать URL-адрес файла в качестве источника.

Посмотрим на общую структуру вызова:


ИмяФайлаНаСервере = ПолучитьИмяВременногоФайла(".jpg"); // Создаем временный файл
Если КопироватьФайл("https://example.com/картинка.jpg", ИмяФайлаНаСервере) Тогда
    // Файл успешно загружен во временный файл
    // Далее можно прочитать его как двоичные данные или вставить в базу
    ДвоичныеДанные = Новый ДвоичныеДанные(ИмяФайлаНаСервере);
    // ... дальнейшая обработка ...
Иначе
    // Ошибка загрузки файла
КонецЕсли;

Однако, важно учитывать некоторые ограничения при использовании этой функции:

  1. На веб-клиенте метод КопироватьФайл работает только с локальными файлами. Это означает, что для загрузки файла из интернета на веб-клиенте напрямую через КопироватьФайл не получится. Файл сначала придется сохранить на локальный диск пользователя, а затем уже использовать КопироватьФайл для работы с ним.
  2. Для работы с файлами на веб-клиенте может потребоваться предварительное подключение расширения работы с файлами.

Таким образом, для универсальной загрузки из интернета, особенно в условиях клиент-серверного взаимодействия и работы в веб-клиенте, мы рекомендуем использовать более гибкий подход с HTTPСоединение и HTTPЗапрос.

Метод 2: Программная загрузка через HTTPСоединение и HTTPЗапрос

Этот подход является наиболее мощным и универсальным для взаимодействия с веб-серверами. Он позволяет нам вручную устанавливать соединения, отправлять запросы, обрабатывать заголовки и получать двоичные данные файла. Мы разберем этот метод по шагам, включая работу с HTTPS и сохранение изображений в присоединенные файлы номенклатуры.

Шаг 1: Парсинг URI ссылки

Прежде чем устанавливать HTTP-соединение, нам необходимо разобрать (спарсить) переданную ссылку на ее составные части: схему (http/https), хост, порт, путь на сервере и, при необходимости, данные авторизации (логин/пароль). Для этого мы можем использовать вспомогательную функцию СтруктураURI.

Вот пример реализации функции СтруктураURI, которая извлекает все необходимые компоненты из URL:


&НаСервере
Функция СтруктураURI(Знач СтрокаURI) Экспорт
    
    СтрокаURI = СокрЛП(СтрокаURI);
    
    // схема
    Схема = "";
    Позиция = Найти(СтрокаURI, "://");
    Если Позиция > 0 Тогда
        Схема = НРег(Лев(СтрокаURI, Позиция - 1));
        СтрокаURI = Сред(СтрокаURI, Позиция + 3);
    КонецЕсли;
    
    // строка соединения и путь на сервере
    СтрокаСоединения = СтрокаURI;
    ПутьНаСервере = "";
    Позиция = Найти(СтрокаСоединения, "/");
    Если Позиция > 0 Тогда
        ПутьНаСервере = Сред(СтрокаСоединения, Позиция + 1);
        СтрокаСоединения = Лев(СтрокаСоединения, Позиция - 1);
    КонецЕсли;
    
    // информация пользователя и имя сервера
    СтрокаАвторизации = "";
    ИмяСервера = СтрокаСоединения;
    Позиция = Найти(СтрокаСоединения, "@");
    Если Позиция > 0 Тогда
        СтрокаАвторизации = Лев(СтрокаСоединения, Позиция - 1);
        ИмяСервера = Сред(СтрокаСоединения, Позиция + 1);
    КонецЕсли;
    
    // логин и пароль
    Логин = СтрокаАвторизации;
    Пароль = "";
    Позиция = Найти(СтрокаАвторизации, ":");
    Если Позиция > 0 Тогда
        Логин = Лев(СтрокаАвторизации, Позиция - 1);
        Пароль = Сред(СтрокаАвторизации, Позиция + 1);
    КонецЕсли;
    
    // хост и порт
    Хост = ИмяСервера;
    Порт = "";
    Позиция = Найти(ИмяСервера, ":");
    Если Позиция > 0 Тогда
        Хост = Лев(ИмяСервера, Позиция - 1);
        Порт = Сред(ИмяСервера, Позиция + 1);
    КонецЕсли;
    
    Результат = Новый Структура;
    Результат.Вставить("Схема", Схема);
    Результат.Вставить("Логин", Логин);
    Результат.Вставить("Пароль", Пароль);
    Результат.Вставить("ИмяСервера", ИмяСервера);
    Результат.Вставить("Хост", Хост);
    Результат.Вставить("Порт", ?(Порт <> "", Число(Порт), Неопределено));
    Результат.Вставить("ПутьНаСервере", ПутьНаСервере);
    
    Возврат Результат;
    
КонецФункции

Эта функция возвращает структуру, которая содержит все необходимые данные для создания HTTP-соединения и запроса. Например, если входная строка "https://user:pass@host.com:8080/path/to/resource.jpg", функция вернет структуру с полями: "Схема" = "https", "Хост" = "host.com", "Порт" = 8080, "ПутьНаСервере" = "path/to/resource.jpg", "Логин" = "user", "Пароль" = "pass".

Шаг 2: Установление HTTP/HTTPS соединения

Для создания соединения используем объект HTTPСоединение. Если ссылка использует протокол HTTPS, нам потребуется объект ЗащищенноеСоединениеOpenSSL для обеспечения безопасного соединения.


СтруктураURI = СтруктураURI(УРЛОсновнойКартинки_); // Используем нашу вспомогательную функцию

Защита = Неопределено;
Если СокрЛП(СтруктураURI.Схема) = "https" Тогда
    Защита = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено);
    // Дополнительно ЗащищенноеСоединениеOpenSSL может принимать параметры для
    // клиентских сертификатов и сертификатов удостоверяющих центров для более строгой аутентификации.
    // Например: Новый ЗащищенноеСоединениеOpenSSL(СертификатКлиента, СертификатыУЦ)
КонецЕсли;

HTTPСоединение = Новый HTTPСоединение(СтруктураURI.Хост, 
                                     ?(СтруктураURI.Порт <> Неопределено, СтруктураURI.Порт, Неопределено),
                                     СтруктураURI.Логин,
                                     СтруктураURI.Пароль,
                                     ,,
                                     Защита);

Обратите внимание, что объект ЗащищенноеСоединениеOpenSSL в веб-клиенте не обеспечивает безопасность соединения, и соединение КриптоПро там не поддерживается. Также мы передаем логин и пароль в конструктор HTTPСоединение, если они были указаны в URI.

Шаг 3: Отправка HTTP-запроса и проверка доступности картинки

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

Рассмотрим пример кода для проверки доступности картинки, который возвращает "Удача" или "Ошибка" в зависимости от HTTP-кода состояния:


HTTPЗапрос = Новый HTTPЗапрос(СтруктураURI.ПутьНаСервере); 
// Для более сложных запросов и интеграций с внешними системами
// может потребоваться установка дополнительных заголовков, например:
// HTTPЗапрос.УстановитьЗаголовок("User-Agent", "1CEnterprise/8.3");
// HTTPЗапрос.УстановитьЗаголовок("Accept", "image/jpeg, image/png, image/*");

Попытка
    Результат = HTTPСоединение.Получить(HTTPЗапрос);
Исключение
    Возврат "Ошибка"; 
КонецПопытки;

// Анализируем код состояния HTTP-ответа
Если Результат.КодСостояния >= 400 И Результат.КодСостояния < 500 Тогда
    // Ошибки клиента (например, 404 Not Found, 403 Forbidden)
    Возврат "Ошибка";
ИначеЕсли Результат.КодСостояния >= 500 И Результат.КодСостояния < 600 Тогда
    // Ошибки сервера (например, 500 Internal Server Error)
    Возврат "Ошибка";
ИначеЕсли Результат.КодСостояния >= 300 И Результат.КодСостояния < 400 Тогда
    // Перенаправления (например, 301 Moved Permanently). 
    // В данном случае мы просто считаем это ошибкой, но можно реализовать логику следования за перенаправлением.
    Возврат "Ошибка";
ИначеЕсли Результат.КодСостояния < 300 Тогда         
    // Успешный ответ (2xx коды, например, 200 OK)
    Возврат "Удача";
КонецЕсли;

В этом коде мы проверяем различные диапазоны HTTP-кодов состояния:

  1. Коды 2xx (например, 200 OK) указывают на успешное выполнение запроса.
  2. Коды 3xx (например, 301 Moved Permanently) означают перенаправление. Для корректной работы часто требуется выполнить повторный запрос по новому адресу, указанному в заголовке Location. В нашем примере мы считаем это ошибкой для простоты.
  3. Коды 4xx (например, 404 Not Found, 403 Forbidden) указывают на ошибки на стороне клиента или некорректный запрос.
  4. Коды 5xx (например, 500 Internal Server Error, 503 Service Unavailable) указывают на ошибки на стороне сервера.

Шаг 4: Загрузка и сохранение картинки в 1С

Если запрос был успешным (код состояния менее 300), мы можем получить тело ответа как двоичные данные и сохранить их. Мы рассмотрим сохранение изображения в присоединенные файлы номенклатуры, что является стандартным подходом в типовых конфигурациях 1С.


// ... код установления соединения и отправки запроса, как в Шаге 2 и 3 ...
// Предполагаем, что Результат.КодСостояния < 300

Если Результат.КодСостояния < 300 Тогда 
    ДвоичныеДанныеКартинки = Результат.ПолучитьТелоКакДвоичныеДанные();
    
    // Создаем уникальное имя для файла во временном хранилище
    НовоеИмяФайла = Новый УникальныйИдентификатор();
    
    // Помещаем двоичные данные во временное хранилище
    // Это важно для передачи больших объемов данных между клиентом и сервером.
    АдресВременногоХранилищаФайла = ПоместитьВоВременноеХранилище(ДвоичныеДанныеКартинки);
    
    // Добавляем файл к объекту Номенклатура как присоединенный файл
    // Предполагается, что у вас есть ссылка на объект Номенклатура
    ПрисоединенныйФайл = ПрисоединенныеФайлы.ДобавитьФайл(Номенклатура, НовоеИмяФайла, СтрЗаменить("картинка.jpg",".",""), ТекущаяДата(), ТекущаяДата(), АдресВременногоХранилищаФайла, "Изображение загружено обработкой");
    
    Если ЗначениеЗаполнено(ПрисоединенныйФайл) Тогда
        // Если это основная картинка, то привязываем ее к реквизиту ФайлКартинки номенклатуры
        Если ЭтоОсновнаяКартинка = Истина Тогда // Предполагается, что есть переменная ЭтоОсновнаяКартинка
            НоменклатураОбъект = Номенклатура.ПолучитьОбъект();
            НоменклатураОбъект.ФайлКартинки = ПрисоединенныйФайл;
            НоменклатураОбъект.Записать();              
        КонецЕсли;
    КонецЕсли;   
КонецЕсли;

Рассмотрим ключевые моменты в этом коде:

  1. ДвоичныеДанныеКартинки = Результат.ПолучитьТелоКакДвоичныеДанные();: Этот метод объекта HTTPОтвет извлекает содержимое ответа сервера в виде двоичных данных, которые идеально подходят для изображений.
  2. НовоеИмяФайла = Новый УникальныйИдентификатор();: Мы генерируем уникальный идентификатор для нового файла, чтобы избежать коллизий имен при сохранении.
  3. АдресВременногоХранилищаФайла = ПоместитьВоВременноеХранилище(ДвоичныеДанныеКартинки);: Этот метод помещает двоичные данные во временное хранилище на сервере 1С. Это стандартный механизм для передачи больших объемов данных между клиентской и серверной частями приложения, а также для временного хранения файлов перед их окончательным размещением.
  4. ПрисоединенныеФайлы.ДобавитьФайл(...): Этот метод является частью стандартной подсистемы "Присоединенные файлы", которая присутствует во многих типовых конфигурациях. Он позволяет прикрепить файл к определенному объекту (в нашем случае, к Номенклатура), сохраняя его в информационной базе или на внешних томах хранения. В качестве параметров указываются владелец файла, уникальный идентификатор, имя, даты создания/изменения, адрес во временном хранилище и описание.
  5. Привязка основной картинки: Если загруженное изображение должно стать основной картинкой для номенклатуры, мы получаем объект номенклатуры, присваиваем ссылку на созданный присоединенный файл реквизиту ФайлКартинки и записываем объект.

Дополнительные аспекты хранения изображений в 1С

При хранении изображений в 1С мы имеем несколько вариантов, каждый из которых имеет свои преимущества и недостатки:

  1. Хранение непосредственно в информационной базе (тип ХранилищеЗначения):
    • Плюсы: Изображения всегда "под рукой", они включаются в выгрузки базы (.dt файл) и резервные копии СУБД. Это исключает необходимость отдельного резервного копирования файлов.
    • Минусы: Увеличивается размер информационной базы, что может влиять на производительность при работе с большими объемами данных и при резервном копировании.
  2. Хранение во внешних файлах на диске:
    • Плюсы: Уменьшает размер информационной базы, может улучшить производительность при работе с самой базой.
    • Минусы: Требует отдельного резервного копирования каталога с файлами. Существует риск рассинхронизации данных, если файл удален или перемещен, а ссылка в базе не обновлена.
  3. Использование томов хранения:
    • Плюсы: В современных типовых конфигурациях 1С часто реализованы тома хранения, которые позволяют вынести файлы за пределы основной базы данных, но при этом управлять ими из 1С. Это позволяет снизить нагрузку на СУБД, улучшить производительность, обеспечить гибкость управления хранилищем и повысить отказоустойчивость.
    • Минусы: Требует настройки и администрирования.

В большинстве случаев для прикрепленных файлов типовые конфигурации используют собственную подсистему, которая позволяет администратору выбрать место хранения (в базе или на томах).

Взаимодействие клиент-сервер при работе с файлами

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

  1. НачатьПомещениеФайлаНаСервер(): Позволяет инициировать процесс загрузки файла с клиента на сервер. Он может работать в интерактивном режиме (с диалогом выбора файлов) и, в отличие от КопироватьФайл, в веб-клиенте не требует установки расширения работы с файлами для загрузки файлов, выбранных пользователем.
  2. НачатьПолучениеФайлаССервера(): Позволяет скачать файл с сервера на клиент.
  3. НачатьЗапросРазрешенияПользователя(): В веб-клиенте может потребоваться запрос разрешения на доступ к диску. Этот метод позволяет запросить разрешение на группу операций, чтобы избежать множественных запросов к пользователю.

Эти методы полезны, когда пользователь сам выбирает файл для загрузки или сохранения, в то время как наш основной метод с HTTPСоединение предназначен для программной загрузки по URL.

Альтернативный подход: Готовые обработки

Если ваша задача — массовая загрузка изображений для товаров, и вы не хотите погружаться в программирование, то существуют готовые обработки и модули, которые автоматизируют этот процесс. Такие обработки, как, например, упомянутая "Загрузка изображений для товара", обычно предлагают расширенный функционал:

  1. Распознавание номенклатуры по артикулу, наименованию или другим условиям.
  2. Предварительный просмотр загружаемых изображений.
  3. Обновление существующих или добавление новых картинок.
  4. Пакетная обработка большого количества ссылок.
  5. Возможность выгрузки изображений из 1С.

Использование готовых решений может значительно ускорить процесс и снизить трудозатраты на разработку и отладку, особенно для не-программистов.

Заключение

Мы рассмотрели различные методы программной загрузки изображений из интернета в 1С. Для простых случаев и локального использования можно применять КопироватьФайл. Однако для универсальных и надежных решений, особенно при работе с HTTPS и в условиях клиент-серверного взаимодействия, наиболее подходящим является использование связки HTTPСоединение и HTTPЗапрос. Этот подход обеспечивает полный контроль над процессом запроса и обработки ответа, позволяя гибко управлять загрузкой и сохранением данных в вашей информационной базе 1С.

Не забывайте о важности правильной обработки ошибок HTTP, управлении защищенными соединениями и эффективных способах хранения файлов в 1С, таких как присоединенные файлы и тома хранения.

← На главную