Как правильно передать изображение в формате Base64 через JSON в 1С?

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

При интеграции 1С с внешними системами (включая Python-коннектор к 1С) через HTTP-сервисы одной из распространенных задач является передача графических данных (фотографий товаров, изображений сотрудников или сканов документов для распознавания). Стандартным способом передачи бинарных данных (который автоматизирует конструктор API) внутри текстового формата JSON является кодирование в Base64. Однако разработчики часто сталкиваются с проблемой: на стороне получателя строка оказывается "битой" или содержит нежелательные символы переноса строк (\n, \r), что мешает корректному декодированию изображения. В этой статье мы подробно разберем, как правильно подготовить картинку, сформировать JSON и избежать типичных ошибок.

Выясним причину появления лишних символов

Разберем ситуацию: почему при использовании стандартной функции Base64Строка() или библиотеки для работы с двоичными данными в итоговом сообщении появляются переносы? Дело в том, что глобальная функция 1С формирует строку в соответствии со стандартом MIME (RFC 2045). Согласно этому стандарту, для обеспечения совместимости со старыми почтовыми системами, в строку должны вставляться символы разрыва строки через каждые 72 или 76 символов.

Для современного JSON-парсера эти символы являются избыточными, а иногда и недопустимыми, если они не экранированы. Если мы просто вставляем такую строку в структуру и сериализуем её, 1С может добавить экранирование (например, превратить символ переноса в последовательность \n), что увеличит объем данных и может привести к ошибке на принимающей стороне.

Метод 1: Программная очистка строки Base64

Самый простой и надежный способ — это принудительное удаление всех символов переноса строк и возврата каретки сразу после преобразования двоичных данных в строку. Проанализируем пример кода, который позволяет это сделать:


Функция ФотоФизЛицаВBase64(ФайлСсылка)
    // Получаем двоичные данные файла
    ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(ФайлСсылка);
    
    // Преобразуем в Base64
    ФотоBase64 = Base64Строка(ДвоичныеДанные);
    
    // Очищаем строку от переносов (Символы.ПС - \n, Символы.ВК - \r)
    ФотоBase64 = СтрЗаменить(ФотоBase64, Символы.ВК, "");
    ФотоBase64 = СтрЗаменить(ФотоBase64, Символы.ПС, "");
    
    Возврат ФотоBase64;
КонецФункции

Рассмотрим более продвинутый вариант очистки, который разом удаляет все возможные "мусорные" символы (пробелы, табуляции и переносы), которые могут возникнуть при чтении данных из необычных источников:


// Удаление всех разделителей через разделение и соединение строки
СписокРазделителей = Символы.ПС + Символы.ВК + Символы.Таб + " ";
ЧастиСтроки = СтрРазделить(ФотоBase64, СписокРазделителей, Ложь);
ФотоBase64 = СтрСоединить(ЧастиСтроки, "");

Метод 2: Использование встроенных методов объекта ДвоичныеДанные

Начиная с версии платформы 8.3.10, у объекта ДвоичныеДанные появился собственный метод для получения Base64. Посмотрим на пример его использования:


ДвоичныеДанныеКартинки = Новый ДвоичныеДанные(ПутьКФайлу);
СтрокаBase64 = ДвоичныеДанныеКартинки.Base64Строка();

Хотя этот метод работает быстрее, важно помнить, что он также может следовать правилам форматирования платформы. Поэтому проверку на наличие переносов строк стоит оставить в любом случае.

Настройка записи JSON для передачи данных

Когда строка подготовлена, нам нужно правильно сформировать JSON-ответ. Проанализируем процесс записи JSON с использованием специализированных объектов платформы. Важно правильно установить параметры записи, чтобы избежать двойного экранирования или проблем с кодировкой.


// Создаем объект записи
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет, " ", Истина);
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);

// Формируем структуру данных
ДанныеДляОтправки = Новый Структура;
ДанныеДляОтправки.Вставить("status", "success");
ДанныеДляОтправки.Вставить("photo", ФотоBase64);

// Записываем данные
ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтправки);
ОтветJSON = ЗаписьJSON.Закрыть();

Обратите внимание на параметр ЭкранироватьРазделителиСтрок в настройках ПараметрыЗаписиJSON. Если установить его в значение Истина, платформа будет корректно обрабатывать управляющие символы, если они всё же остались в строке. Однако для чистоты данных лучше передавать строку без них.

Настройка заголовков HTTP-ответа

Для того чтобы принимающая сторона (браузер, мобильное приложение или другой сервер) правильно интерпретировала полученные данные, необходимо верно указать Content-Type в заголовках ответа HTTP-сервиса. Посмотрим, как это сделать — для отладки и логирования таких запросов пригодится модуль логирования HTTP-запросов и JSON-ответов.


Ответ = Новый HTTPСервисОтвет(200);
// Указываем, что передаем именно JSON, а не обычный текст или HTML
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(ОтветJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Возврат Ответ;

Использование application/json вместо text/html является критически важным стандартом для REST-интерфейсов — развернуть готовый обмен поможет готовое решение REST API для интеграции 1С через HTTP-сервисы.

Оптимизация объема данных

Передача изображений в формате Base64 имеет один существенный недостаток: объем данных увеличивается примерно на 33% по сравнению с исходным бинарным файлом. Рассмотрим, как мы можем оптимизировать этот процесс:

  1. Сжатие изображения: Перед конвертацией в Base64 мы можем изменить размер картинки или снизить её качество. В 1С для этого можно использовать объект Картинка — для автоматической оптимизации файлов подойдёт обработка сжатия и изменения разрешения изображений.
  2. Проверка лимитов веб-сервера: Если вы используете IIS или Apache, убедитесь, что лимит на размер тела запроса (например, maxAllowedContentLength в конфигурации IIS) позволяет передавать файлы нужного размера.
  3. Кеширование: Если картинки меняются редко, передавайте их MD5-хеш, чтобы клиент мог запросить обновление только при изменении файла.

Пример уменьшения картинки перед отправкой:


КартинкаОригинал = Новый Картинка(ПутьКФайлу);
// Допустим, нам нужно превью 200x200
ОбработаннаяКартинка = КартинкаОригинал.Преобразовать(ФорматКартинки.JPEG); 
// Здесь можно использовать компоненты для изменения размера
ДвоичныеДанныеДляОтправки = ОбработаннаяКартинка.ПолучитьДвоичныеДанные();

Альтернативный подход: Передача бинарных данных напрямую

Проанализируем ситуацию, когда передача через Base64 внутри JSON не является обязательной. Если архитектура позволяет, гораздо эффективнее передавать файл напрямую в теле HTTP-ответа. Разберем, как это реализовать:

  1. Установите заголовок Content-Type: image/jpeg (или другой соответствующий формат).
  2. Используйте метод Ответ.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанные).

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

Таким образом, мы рассмотрели все основные аспекты работы с изображениями в JSON. Помните, что чистота строки Base64 и правильные HTTP-заголовки — залог стабильной работы вашей интеграции.

← На главную