В современной разработке на платформе 1С:Предприятие 8.3 часто возникает задача интеграции различных систем, где требуется передача не только текстовой информации, но и бинарных данных, таких как изображения. Рассмотрим ситуацию, когда нам необходимо передать картинку с клиента на сторону HTTP-сервиса и сохранить её в информационной базе (например, в ресурсе регистра сведений или реквизите справочника). Проанализируем несколько подходов, разберем их преимущества и приведем примеры реализации. Для упрощения разработки серверной части можно использовать готовый общий модуль для организации HTTP-сервисов.
Этот метод считается наиболее производительным и "чистым" с точки зрения использования протокола HTTP. Вместо того чтобы упаковывать файл в дополнительные форматы, мы отправляем "сырые" двоичные данные. Рассмотрим, как реализовать отправку на стороне клиента и получение на стороне сервера.
На стороне клиента мы считываем файл в объект ДвоичныеДанные и помещаем его в тело запроса:
// Клиентский код (отправка)
КартинкаОбъект = Новый Картинка("C:\temp\image.jpg");
ДвоичныеДанные = КартинкаОбъект.ПолучитьДвоичныеДанные();
Запрос = Новый HTTPЗапрос("/hs/MyService/UploadImage");
Запрос.Заголовки.Вставить("Content-Type", "image/jpeg");
Запрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанные);
Соединение = Новый HTTPСоединение("myserver.com");
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
На стороне HTTP-сервиса в методе POST мы извлекаем данные. Проанализируем, как это сделать правильно:
// Код метода HTTP-сервиса (прием)
Функция UploadImagePost(Запрос)
ДвоичныеДанные = Запрос.ПолучитьТелоКакДвоичныеДанные();
// Проверим, что данные действительно являются картинкой
Попытка
ТестоваяКартинка = Новый Картинка(ДвоичныеДанные);
Исключение
Возврат Новый HTTPСервисОтвет(400); // Bad Request
КонецПопытки;
// Сохранение в регистр или справочник
НоваяЗапись = РегистрыСведений.ХранилищеИзображений.СоздатьМенеджерЗаписи();
НоваяЗапись.ИмяФайла = "uploaded_image.jpg";
НоваяЗапись.ДанныеФайла = Новый ХранилищеЗначения(ДвоичныеДанные);
НоваяЗапись.Записать();
Возврат Новый HTTPСервисОтвет(200);
КонецФункции
Если ваш HTTP-сервис спроектирован по принципам REST и работает с JSON-объектами, наиболее логичным будет передать картинку как одну из строк в JSON. Поскольку JSON не поддерживает бинарные данные напрямую, мы преобразуем их в строку с помощью алгоритма Base64. Стоит учитывать, что это увеличивает размер передаваемых данных примерно на 33%. Для тестирования и отладки создаваемого REST API пригодится инструмент для проверки HTTP-запросов на платформе 1С.
Разберем по шагам процесс упаковки данных:
ДвоичныеДанные из файла.Base64Строка().
// Подготовка данных на клиенте
ДвоичныеДанные = Новый ДвоичныеДанные("C:\photo.png");
СтрокаBase64 = Base64Строка(ДвоичныеДанные);
ДанныеДляОтправки = Новый Структура;
ДанныеДляОтправки.Вставить("FileName", "photo.png");
ДанныеДляОтправки.Вставить("Content", СтрокаBase64);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтправки);
ТелоЗапроса = ЗаписьJSON.Закрыть();
На стороне сервера выполняем обратную операцию. Мы считываем JSON, извлекаем строку и превращаем её обратно в ДвоичныеДанные с помощью функции Base64Значение().
// Обработка на сервере
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
СтруктураДанных = ПрочитатьJSON(ЧтениеJSON);
Если СтруктураДанных.Свойство("Content") Тогда
КартинкаБинар = Base64Значение(СтруктураДанных.Content);
// Далее записываем КартинкаБинар в ХранилищеЗначения
КонецЕсли;
Выясним причину популярности этого метода: он позволяет передавать одновременно и файлы, и текстовые поля (метаданные) без сложного кодирования всего тела запроса. В 1С это реализуется через формирование составного тела запроса с разделителями (boundary).
Рассмотрим структуру такого запроса. Мы должны вручную или с помощью специализированных библиотек сформировать поток, в котором будут указаны границы частей данных и их типы. Это особенно удобно, если вы загружаете сразу несколько изображений одним пакетом.
После того как данные получены HTTP-сервисом, важно убедиться в их корректности перед записью в базу. Проанализируем лучшие практики:
Новый Картинка(ДвоичныеДанные). Если это вызывает исключение, значит, данные повреждены или передается не изображение.ХранилищеЗначения для реквизитов, где будут лежать бинарные данные. Это позволит платформе эффективно управлять памятью и сжимать данные при необходимости.ОбработкаКартинок. Это сэкономит трафик и место на сервере.Важно помнить, что при работе через HTTP-сервисы запросы проходят через веб-сервер (IIS или Apache). По умолчанию в них стоят ограничения на объем передаваемого тела запроса (часто это 2 МБ или 30 МБ). Если вы попытаетесь передать файл большего размера, 1С даже не получит запрос, так как веб-сервер вернет ошибку 413 Entity Too Large.
Для IIS необходимо отредактировать файл web.config, изменив параметр maxAllowedContentLength. Для Apache следует обратить внимание на директиву LimitRequestBody в конфигурационном файле httpd.conf.
В завершение отметим, что выбор метода зависит от архитектуры вашего решения. Если вы строите универсальное API, используйте JSON + Base64. Если важна максимальная скорость передачи больших файлов — выбирайте Binary Stream. Использование встроенных функций ЗначениеВФайл и ЗначениеИзФайла, как упоминалось в обсуждении, также возможно для быстрой сериализации внутренних объектов 1С, но этот метод менее универсален при взаимодействии с внешними системами.