Почему картинка из Base64 в 1С получается нулевого размера и как это исправить?

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

Работа с внешними сервисами через API практически всегда подразумевает обмен данными в формате Base64. Это стандартный способ передачи бинарных данных (например, изображений товаров) внутри текстовых пакетов JSON или XML. Однако программисты 1С часто сталкиваются с ситуацией: код выполняется без ошибок, файл на диске создается, но его размер равен 0 байт, либо объект Картинка остается пустым. Разберем по шагам, почему это происходит и как гарантированно получить валидное изображение.

Анализируем исходную ситуацию

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


Бэйз64Строка = РазобранныйМассивТоваров[Индекс3]; 
            
Бэйз64Строка = СтрЗаменить(Бэйз64Строка, Символы.ВК, "");
Бэйз64Строка = СтрЗаменить(Бэйз64Строка, Символы.ПС, "");
Бэйз64Строка = СтрЗаменить(Бэйз64Строка, "\n", ""); 

ИзображениеНоменклатуры = Новый Картинка(Base64Значение(СокрЛП(Бэйз64Строка)));      
      
ПутьКФайлу = "C:\temp\NomImWS.jpg";
Попытка
    ИзображениеНоменклатуры.Записать(ПутьКФайлу);
Исключение
    Сообщить(ОписаниеОшибки());
КонецПопытки;

Проблема заключается в том, что метод Base64Значение() крайне чувствителен к любым посторонним символам в строке. Если онлайн-декодеры в браузере умеют "прощать" ошибки форматирования, то встроенные механизмы платформы 1С требуют идеально чистую последовательность символов алфавита Base64.

Выясняем основную причину: Экранирование в JSON

Проанализируем структуру строки, которую прислал сервис. Часто в JSON-ответах символы прямого слэша / (который является частью алфавита Base64) заменяются на экранированную последовательность \/.

Для JSON это стандартное поведение, но для функции Base64Значение символ обратного слэша \ является мусором. Именно из-за него алгоритм декодирования прерывается, возвращая пустой результат.

Решение: Нам необходимо обязательно удалить все символы обратного слэша из полученной строки перед обработкой.


// Удаляем символы экранирования, которые часто встречаются в JSON
Бэйз64Строка = СтрЗаменить(Бэйз64Строка, "\", "");

Разберем дополнительные факторы, влияющие на результат

Помимо экранирования слэшей, существует еще несколько критических моментов, которые мы должны проверить, если картинка все равно не сохраняется:

  1. Префикс Data URI: Многие современные веб-сервисы передают строку вместе с заголовком вида data:image/jpeg;base64,. Если этот заголовок попадет в метод Base64Значение, картинка будет пустой. Нам нужно найти позицию первой запятой и взять только ту часть строки, которая идет после нее.
  2. Неразрывные пробелы: Иногда при передаче данных в строку попадают невидимые символы с кодом 160 (неразрывный пробел). Обычный СокрЛП их не удаляет.
  3. Кратность строки 4 (Padding): Строка Base64 должна иметь длину, кратную четырем. Если данных не хватает, в конце добавляются символы =. Если сервис "обрезал" эти символы, 1С может не распознать строку.

Реализуем надежный метод очистки и сохранения

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


// Функция для безопасного получения картинки из Base64
Функция ПолучитьКартинкуИзBase64(Знач ВходящаяСтрока)
    
    // 1. Очистка от служебных символов JSON и переносов
    ЧистаяСтрока = СтрЗаменить(ВходящаяСтрока, "\", "");
    ЧистаяСтрока = СтрЗаменить(ЧистаяСтрока, Символы.ПС, "");
    ЧистаяСтрока = СтрЗаменить(ЧистаяСтрока, Символы.ВК, "");
    ЧистаяСтрока = СтрЗаменить(ЧистаяСтрока, " ", ""); // Удаляем обычные пробелы
    
    // 2. Проверка на наличие префикса "data:..."
    ПозицияЗапятой = Найти(ЧистаяСтрока, ",");
    Если ПозицияЗапятой > 0 Тогда
        ЧистаяСтрока = Сред(ЧистаяСтрока, ПозицияЗапятой + 1);
    КонецЕсли;
    
    Попытка
        // Используем современный метод преобразования
        ДвоичныеДанные = Base64СтрокаВДвоичныеДанные(ЧистаяСтрока);
        
        // Проверяем, что данные не пустые
        Если ДвоичныеДанные.Размер() > 0 Тогда
            Возврат Новый Картинка(ДвоичныеДанные);
        Иначе
            Возврат Неопределено;
        КонецЕсли;
    Исключение
        ЗаписатьЛогОшибок(ОписаниеОшибки());
        Возврат Неопределено;
    КонецПопытки;
    
КонецФункции

Посмотрим на особенности записи на диск

Важно помнить, где именно выполняется ваш код. Если вы работаете в Тонком клиенте, прямой вызов Картинка.Записать(Путь) может столкнуться с ограничениями прав доступа к файловой системе сервера или клиента.

Рекомендуемый порядок действий:

Итоговое резюме

Если вы получаете картинку нулевого размера из Base64, первым делом выполните СтрЗаменить(Бэйз64Строка, "\", ""). В 90% случаев при интеграции с веб-сервисами проблема кроется именно в этом. Вторым шагом проверьте строку на наличие префикса data:image/...;base64, и удалите его. Используйте современные методы Base64СтрокаВДвоичныеДанные вместо Base64Значение для лучшей диагностики ошибок.

← На главную