Когда мы сталкиваемся с задачей получения сканов документов, таких как PDF или JPEG, через HTTP-сервис в информационную систему на базе 1С, перед нами встает вопрос о наиболее подходящем и эффективном методе передачи двоичных данных. В процессе обсуждения этой темы на форуме 1С были высказаны различные мнения и предложены рабочие решения, которые мы сейчас подробно рассмотрим.
Изначально автор темы предположил, что для передачи сканов через HTTP-сервис, где 1С выступает в роли принимающей стороны, а сторонняя система (клиент) – в роли отправителя, оптимальным будет преобразование файла (будь то PDF или JPEG) в строку формата Base64 и передача этой строки внутри JSON-сообщения. На стороне 1С планировалось выполнить обратное преобразование из Base64 в двоичные данные, а затем использовать функционал БСП (Библиотеки стандартных подсистем) РаботаСФайлами.ДобавитьФайл для сохранения полученного документа.
Главный вопрос, который волновал автора: является ли Base64 единственным вариантом, и можно ли работать с другими форматами или напрямую с двоичными данными, переданными в виде строки? Давайте разберем, как это работает и какие альтернативы существуют.
Что такое "двоичные данные"?
Для начала, давайте проясним терминологию. Когда мы говорим о "двоичных данных", мы имеем в виду любую информацию, представленную в виде последовательности нулей и единиц (битов), которая не является текстовой в обычном понимании. Изображения (JPEG, PNG), документы (PDF, DOCX), аудио- и видеофайлы — все это примеры двоичных данных. Для HTTP-протокола это означает, что содержимое передается "как есть", байт за байтом, и обычно сопровождается заголовком Content-Type, указывающим на тип передаваемого файла (например, image/jpeg или application/pdf).
Сложность возникает, когда эти двоичные данные нужно встроить в текстовые форматы, такие как JSON или XML. Эти форматы предназначены для передачи текстовых строк, чисел, булевых значений и структур из них. Прямое включение двоичных байтов в JSON может привести к проблемам с кодировкой, повреждению данных или нарушению структуры JSON. Для решения этой проблемы используются методы кодирования, которые преобразуют двоичные данные в текст.
Один из самых распространенных и удобных способов передачи двоичных данных внутри текстовых форматов, таких как JSON, — это кодирование с использованием алгоритма Base64. Этот метод был основным в первоначальной задумке автора.
Метод Base64 позволяет кодировать произвольные двоичные данные в текстовую строку, используя алфавит из 64 символов (латинские буквы верхнего и нижнего регистра, цифры и два дополнительных символа, обычно '+' и '/'). Этот текстовый формат безопасен для передачи через каналы, которые могут быть ориентированы на текст и иметь ограничения на использование определенных нетекстовых символов. На стороне приемника закодированная строка Base64 может быть легко декодирована обратно в исходные двоичные данные.
Преимущества Base64:
Base64Строка() преобразует двоичные данные в строку Base64, а Base64Значение() выполняет обратное преобразование.Недостатки Base64:
Для приема данных в 1С, когда клиент отправляет Base64-строку внутри JSON, нам потребуется выполнить следующие шаги:
Base64Значение() для преобразования строки в объект ДвоичныеДанные.ДвоичныеДанные как присоединенный файл, например, с помощью функционала БСП.Пример получения из JSON и декодирования в 1С:
// Предположим, что мы находимся в процедуре обработки HTTP-сервиса
// и у нас есть объект HTTPСервисЗапрос.
// 1. Получаем тело HTTP-запроса как JSON-строку.
// Важно убедиться, что клиент отправляет JSON с соответствующим Content-Type: application/json
JSONСтрока = HTTPСервисЗапрос.ПолучитьТелоКакСтроку();
// 2. Десериализуем JSON-строку в структуру или соответствие 1С.
ПеременнаяДляЧтенияJSON = Новый ЧтениеJSON;
Попытка
ПеременнаяДляЧтенияJSON.УстановитьСтроку(JSONСтрока);
ДанныеИзJSON = ПрочитатьJSON(ПеременнаяДляЧтенияJSON);
Исключение
// Обработка ошибки, если JSON некорректен
ВызватьИсключение "Ошибка десериализации JSON: " + ОписаниеОшибки();
КонецПопытки;
ПеременнаяДляЧтенияJSON.Закрыть();
// 3. Предполагаем, что Base64 строка содержится в ключе "ФайлBase64",
// а имя файла и его тип могут быть в отдельных ключах.
СтрокаBase64 = ДанныеИзJSON.Получить("ФайлBase64");
Если СтрокаBase64 = Неопределено Тогда
ВызватьИсключение "В JSON не найдено поле 'ФайлBase64'.";
КонецЕсли;
// Также получаем имя и тип файла, если они передаются
ИмяФайла = ДанныеИзJSON.Получить("ИмяФайла");
Если ИмяФайла = Неопределено Тогда
ИмяФайла = "СканированныйДокумент.bin"; // Имя по умолчанию, если не указано
КонецЕсли;
РасширениеФайла = ДанныеИзJSON.Получить("РасширениеФайла"); // Например, "pdf", "jpeg"
Если РасширениеФайла = Неопределено Тогда
// Попытаемся извлечь расширение из имени файла, если оно там есть
ПозицияТочки = СтрНайти(ИмяФайла, ".", , , Ложь); // Ищем с конца
Если ПозицияТочки > 0 Тогда
РасширениеФайла = Сред(ИмяФайла, ПозицияТочки + 1);
Иначе
РасширениеФайла = "bin"; // Расширение по умолчанию
КонецЕсли;
КонецЕсли;
// Убедимся, что имя файла содержит расширение
Если СтрНайти(ИмяФайла, ".") = 0 И СтрДлина(РасширениеФайла) > 0 Тогда
ИмяФайла = ИмяФайла + "." + РасширениеФайла;
КонецЕсли;
// 4. Преобразуем строку Base64 в объект ДвоичныеДанные.
ДвоичныеДанныеФайла = Неопределено;
Попытка
ДвоичныеДанныеФайла = Base64Значение(СтрокаBase64);
Исключение
ВызватьИсключение "Ошибка преобразования Base64-строки в двоичные данные: " + ОписаниеОшибки();
КонецПопытки;
Если ДвоичныеДанныеФайла = Неопределено Тогда
ВызватьИсключение "Не удалось получить двоичные данные из Base64-строки.";
КонецЕсли;
// 5. Сохраняем файл с помощью БСП РаботаСФайлами.ДобавитьФайл.
// Для этого нам нужен объект-владелец, к которому будет присоединен файл.
// Например, это может быть элемент справочника "Договоры", "Номенклатура"
// или объект документа, к которому относится скан.
// Пример: находим или создаем владельца файла (например, Договор)
ВладелецФайла = Справочники.Договоры.НайтиПоКоду("Договор00001");
Если ВладелецФайла = Неопределено Тогда
// Если владельца нет, можем создать новый или выбрать существующий по другой логике
ВладелецФайла = Справочники.Договоры.СоздатьЭлемент();
ВладелецФайла.Наименование = "Входящий скан по договору";
ВладелецФайла.Код = "Договор00001";
Попытка
ВладелецФайла.Записать();
Исключение
ВызватьИсключение "Ошибка записи владельца файла: " + ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
// Добавляем файл через БСП
Попытка
РезультатДобавления = РаботаСФайлами.ДобавитьФайл(
ДвоичныеДанныеФайла, // Объект ДвоичныеДанные
ИмяФайла, // Имя файла, например, "СканДоговора_123.pdf"
ВладелецФайла, // Объект, к которому прикрепляем файл
Неопределено, // ВнешнийID - если нужно связать с внешней системой
РасширениеФайла, // Расширение файла (например, "pdf")
ДанныеИзJSON.Получить("Комментарий") // Комментарий к файлу
);
Если РезультатДобавления = Неопределено Тогда
ВызватьИсключение "Не удалось добавить файл через БСП.";
КонецЕсли;
Исключение
ВызватьИсключение "Ошибка добавления файла через БСП: " + ОписаниеОшибки();
КонецПопытки;
// Отправляем успешный ответ клиенту
HTTPСервисОтвет.КодСостояния = 200;
HTTPСервисОтвет.УстановитьТелоИзСтроки("{\"Статус\": \"Успех\", \"Сообщение\": \"Файл успешно принят.\"}", "application/json", КодировкаТекста.UTF8);
Если клиент не передает данные в JSON, а отправляет "чистые" двоичные данные (например, один файл) напрямую в теле HTTP-запроса, то это может быть более эффективным способом, особенно для больших файлов, так как исключает накладные расходы на кодирование/декодирование Base64.
HTTP-протокол изначально был разработан для передачи разнообразных данных, включая двоичные. Когда клиент отправляет файл напрямую, он помещает его содержимое в тело HTTP-запроса. Для корректной обработки на стороне сервера очень важно правильно установить заголовок Content-Type в HTTP-запросе, который будет указывать на тип отправляемого файла (например, application/pdf для PDF-файла или image/jpeg для JPEG-изображения).
Особенности:
Content-Type: Заголовок Content-Type критически важен, так как он сообщает серверу (1С) о формате данных в теле запроса.X-File-Name: document.pdf).На стороне 1С для получения тела запроса как двоичных данных используем метод ПолучитьТелоКакДвоичныеДанные() объекта HTTPСервисЗапрос. Этот метод позволяет напрямую получить содержимое тела запроса в виде объекта ДвоичныеДанные.
Пример получения и сохранения:
// Предположим, что мы находимся в процедуре обработки HTTP-сервиса
// и клиент отправил PDF или JPEG файл напрямую в теле запроса.
// 1. Извлекаем двоичные данные напрямую из тела запроса.
// Если клиент отправил пустой запрос, то ДвоичныеДанныеФайла будет пустым.
ДвоичныеДанныеФайла = HTTPСервисЗапрос.ПолучитьТелоКакДвоичныеДанные();
Если ДвоичныеДанныеФайла.Размер() = 0 Тогда
ВызватьИсключение "Тело запроса не содержит двоичных данных или оно пусто.";
КонецЕсли;
// 2. Получаем имя файла и тип из заголовков или параметров запроса.
// Рекомендуется передавать эти данные в заголовках.
ИмяФайла = HTTPСервисЗапрос.Заголовки.Получить("X-File-Name"); // Кастомный заголовок с именем файла
Если ИмяФайла = Неопределено Тогда
ИмяФайла = "СканированныйДокумент"; // Имя по умолчанию
КонецЕсли;
// 3. Определяем расширение файла по заголовку Content-Type.
ТипКонтента = HTTPСервисЗапрос.Заголовки.Получить("Content-Type");
РасширениеФайла = "bin"; // Расширение по умолчанию, если тип не распознан
Если ТипКонтента <> Неопределено Тогда
Если Найти(ТипКонтента, "application/pdf") <> 0 Тогда
РасширениеФайла = "pdf";
ИначеЕсли Найти(ТипКонтента, "image/jpeg") <> 0 Тогда
РасширениеФайла = "jpeg";
ИначеЕсли Найти(ТипКонтента, "image/png") <> 0 Тогда
РасширениеФайла = "png";
ИначеЕсли Найти(ТипКонтента, "application/zip") <> 0 Тогда
РасширениеФайла = "zip";
КонецЕсли;
КонецЕсли;
// 4. Убедимся, что имя файла содержит расширение
Если СтрНайти(ИмяФайла, ".") = 0 И СтрДлина(РасширениеФайла) > 0 Тогда
ИмяФайла = ИмяФайла + "." + РасширениеФайла;
КонецЕсли;
// 5. Получаем дополнительные метаданные, если они передаются (например, ID владельца)
// Допустим, ID владельца передается в кастомном заголовке X-Owner-ID
ИдентификаторВладельца = HTTPСервисЗапрос.Заголовки.Получить("X-Owner-ID");
// 6. Сохраняем файл с помощью БСП РаботаСФайлами.ДобавитьФайл.
// Логика определения владельца файла аналогична предыдущему примеру.
ВладелецФайла = Неопределено;
Если ИдентификаторВладельца <> Неопределено Тогда
// Ищем владельца по идентификатору
ВладелецФайла = Справочники.Договоры.НайтиПоКоду(ИдентификаторВладельца); // Пример поиска
КонецЕсли;
Если ВладелецФайла = Неопределено Тогда
// Если владелец не найден или не передан, используем заглушку или вызываем ошибку
ВладелецФайла = Справочники.Договоры.НайтиПоКоду("ДоговорПоУмолчанию");
Если ВладелецФайла = Неопределено Тогда
ВладелецФайла = Справочники.Договоры.СоздатьЭлемент();
ВладелецФайла.Наименование = "Договор по умолчанию для сканов";
ВладелецФайла.Код = "ДоговорПоУмолчанию";
ВладелецФайла.Записать();
КонецЕсли;
КонецЕсли;
Попытка
РезультатДобавления = РаботаСФайлами.ДобавитьФайл(
ДвоичныеДанныеФайла, // Объект ДвоичныеДанные
ИмяФайла, // Имя файла
ВладелецФайла, // Объект-владелец
Неопределено, // ВнешнийID
РасширениеФайла // Расширение файла
);
Если РезультатДобавления = Неопределено Тогда
ВызватьИсключение "Не удалось добавить файл через БСП.";
КонецЕсли;
Исключение
ВызватьИсключение "Ошибка добавления файла через БСП: " + ОписаниеОшибки();
КонецПопытки;
// Отправляем успешный ответ
HTTPСервисОтвет.КодСостояния = 200;
HTTPСервисОтвет.УстановитьТелоИзСтроки("{\"Статус\": \"Успех\", \"Сообщение\": \"Файл успешно принят прямым методом.\"}", "application/json", КодировкаТекста.UTF8);
Для более "кошерной" и гибкой передачи файлов, особенно когда вместе с файлом необходимо отправить несколько текстовых полей (например, идентификатор документа, его описание, дату), стандарт HTTP предлагает формат multipart/form-data. Этот метод часто используется при отправке форм с файлами через веб-браузеры.
Формат multipart/form-data используется в HTTP для отправки составных сообщений. Тело запроса делится на несколько "частей" (parts), каждая из которых может содержать свои заголовки (например, Content-Disposition для указания имени поля формы или имени файла, Content-Type для типа содержимого части) и собственные данные. Части отделяются друг от друга специальной "границей" (boundary), которая указывается в заголовке Content-Type основного запроса.
Преимущества:
Прием multipart/form-data в 1С сложнее, чем предыдущие методы, так как платформа не предоставляет готового объекта-парсера для автоматического разбора таких запросов в контексте HTTP-сервисов. Нам потребуется вручную парсить тело запроса, чтобы выделить отдельные части и извлечь из них файлы и метаданные.
Для этого мы должны:
boundary из заголовка Content-Type основного запроса.boundary на отдельные части.Content-Disposition, Content-Type) для определения типа данных (файл или текстовое поле) и получения метаданных (имя файла, имя поля).Пример (концептуальный, так как требует сложной логики парсинга, которую нужно будет реализовать самостоятельно или найти готовую библиотеку/обработку):
// Предположим, что мы находимся в процедуре обработки HTTP-сервиса
// и клиент отправил запрос в формате multipart/form-data.
// 1. Получаем тело запроса как строку.
// Хотя для двоичных данных лучше получить как ДвоичныеДанные,
// для парсинга текстовых границ удобно работать со строкой.
// Если файл очень большой, можно получать частями или использовать другие подходы.
ТелоЗапросаСтрокой = HTTPСервисЗапрос.ПолучитьТелоКакСтроку();
// 2. Извлекаем boundary из заголовка Content-Type.
ЗаголовокContentType = HTTPСервисЗапрос.Заголовки.Получить("Content-Type");
Граница = "";
Если ЗаголовокContentType <> Неопределено Тогда
НачалоГраницы = СтрНайти(ЗаголовокContentType, "boundary=");
Если НачалоГраницы <> 0 Тогда
Граница = Сред(ЗаголовокContentType, НачалоГраницы + СтрДлина("boundary="));
// Граница может быть заключена в кавычки, их нужно удалить
Граница = СтрЗаменить(Граница, """", "");
КонецЕсли;
КонецЕсли;
Если СтрДлина(Граница) = 0 Тогда
ВызватьИсключение "Не удалось определить границу (boundary) для multipart/form-data.";
КонецЕсли;
// 3. Здесь потребуется сложная логика для разделения ТелоЗапросаСтрокой по Границе.
// Каждая часть будет начинаться с "--" + Граница, а последняя часть заканчивается "--" + Граница + "--".
// Примерная структура части:
// --[Граница]
// Content-Disposition: form-data; name="имя_поля"; filename="имя_файла.расширение"
// Content-Type: application/pdf
//
// [Двоичные данные файла или значение поля]
// Для упрощения, предположим, что у нас есть функция ПарситьMultipartFormData,
// которая возвращает Соответствие, где ключи - имена полей/файлов, а значения - их содержимое.
// Это может быть очень сложная функция, которая включает:
// - Разделение строки по границам.
// - Извлечение заголовков Content-Disposition и Content-Type для каждой части.
// - Определение, является ли часть файлом (по наличию "filename" в Content-Disposition).
// - Декодирование содержимого части (если это файл, извлечение двоичных данных).
// СоответствиеДанных = ПарситьMultipartFormData(ТелоЗапросаСтрокой, Граница);
// Предположим, что ПарситьMultipartFormData возвращает:
// - Для текстовых полей: Соответствие.Получить("ТекстовоеПоле") -> "Значение"
// - Для файлов: Соответствие.Получить("ИмяФайловогоПоля") -> ДвоичныеДанные
// Пример получения данных после парсинга
// ИмяФайловогоПоля = "scanFile"; // Как оно указано в name="..." в Content-Disposition
// ДвоичныеДанныеФайла = СоответствиеДанных.Получить(ИмяФайловогоПоля);
// ИмяФайла = СоответствиеДанных.Получить("ИмяФайла_" + ИмяФайловогоПоля); // Если парсер извлек отдельно
// РасширениеФайла = СоответствиеДанных.Получить("РасширениеФайла_" + ИмяФайловогоПоля);
// IDВладельца = СоответствиеДанных.Получить("ownerId"); // Текстовое поле
// ... Далее логика сохранения файла через БСП, как в предыдущих примерах ...
// Если реализация парсинга multipart/form-data кажется слишком сложной,
// рассмотрите использование сторонних библиотек или пересмотр архитектуры
// в пользу Base64 (для небольших файлов) или прямой передачи (для файлов без метаданных).
Реализация парсинга multipart/form-data в 1С требует достаточно глубоких знаний о строковых операциях и работе с двоичными данными, а также понимания структуры HTTP-запросов. Если такой парсер не является критически важным для вашей системы и файлы не очень велики, варианты с Base64 или прямой передачей двоичных данных могут быть более простыми в реализации.
При работе с файлами через HTTP-сервисы, особенно сканами документов, следует учитывать несколько дополнительных аспектов, которые могут значительно улучшить производительность и надежность системы.
Для уменьшения объема передаваемых данных, особенно для больших файлов, можно использовать сжатие. Наиболее распространенный способ — это архивирование в формат ZIP. Клиент может сжимать файл перед отправкой, а 1С — распаковывать его после получения. Это снижает нагрузку на сеть, но добавляет нагрузку на ЦПУ для сжатия и распаковки.
На стороне клиента:
// Пример концептуального сжатия файла в ZIP на стороне клиента:
// Создать ZIP-архив из исходного файла
// Прочитать содержимое ZIP-архива в двоичные данные
// Отправить эти двоичные данные (либо как Base64, либо напрямую)
На стороне 1С, после получения сжатых двоичных данных (например, в формате ZIP):
// Предположим, ДвоичныеДанныеФайла содержат ZIP-архив
ЧтениеZIP = Новый ЧтениеZIP(ДвоичныеДанныеФайла);
СписокФайловВАрхиве = ЧтениеZIP.ПолучитьФайлы();
Для Каждого ЭлементФайла Из СписокФайловВАрхиве Цикл
// ЭлементФайла.Имя содержит имя файла внутри архива
// ЭлементФайла.ДвоичныеДанные - это содержимое файла
// Получаем распакованные двоичные данные
РаспакованныеДвоичныеДанные = ЭлементФайла.ДвоичныеДанные;
ИмяФайлаВнутриАрхива = ЭлементФайла.Имя;
// Далее сохраняем РаспакованныеДвоичныеДанные
// как обычный файл через РаботаСФайлами.ДобавитьФайл
// ... логика сохранения ...
КонецЦикла;
ЧтениеZIP.Закрыть();
При работе с файлами, размер которых может превышать лимиты веб-сервера на размер HTTP-запроса (например, 30 МБ для IIS, 16 МБ для Apache) или просто быть слишком большим для однократной передачи, целесообразно использовать подход с разделением файла на части (чанками).
ДвоичныеДанные, а затем сохраняет окончательный файл и удаляет временные части.Концептуальный пример сборки частей в 1С:
// Этап 1: Получение части (Chunk) в процедуре HTTP-сервиса
// Клиент отправляет каждую часть как прямые двоичные данные
ДвоичныеДанныеЧасти = HTTPСервисЗапрос.ПолучитьТелоКакДвоичныеДанные();
Если ДвоичныеДанныеЧасти.Размер() = 0 Тогда
ВызватьИсключение "Пустая часть файла получена.";
КонецЕсли;
// Метаданные о частях передаются в заголовках или параметрах URL
ИдентификаторФайла = HTTPСервисЗапрос.Заголовки.Получить("X-File-ID"); // Уникальный ID всего файла
НомерЧасти = Число(HTTPСервисЗапрос.Заголовки.Получить("X-Chunk-Number")); // Номер текущей части
ОбщееКоличествоЧастей = Число(HTTPСервисЗапрос.Заголовки.Получить("X-Total-Chunks"));
ИмяИсходногоФайла = HTTPСервисЗапрос.Заголовки.Получить("X-Original-Filename");
Если ИдентификаторФайла = Неопределено ИЛИ НомерЧасти = Неопределено ИЛИ
ОбщееКоличествоЧастей = Неопределено Тогда
ВызватьИсключение "Недостаточно метаданных для частичной загрузки файла.";
КонецЕсли;
// Этап 2: Сохранение части во временное хранилище (например, в отдельную папку)
ПутьКВременнойПапкеДляЗагрузки = КаталогВременныхФайлов() + "ЗагрузкаФайлов_" + ИдентификаторФайла + "\";
СоздатьКаталог(ПутьКВременнойПапкеДляЗагрузки);
ИмяВременногоФайлаЧасти = ПутьКВременнойПапкеДляЗагрузки + Формат(НомерЧасти, "Ч(0,3,'0')") + ".tmp"; // Например, 001.tmp, 002.tmp
ДвоичныеДанныеЧасти.Записать(ИмяВременногоФайлаЧасти);
// Отправляем ответ, что часть успешно принята
HTTPСервисОтвет.КодСостояния = 200;
HTTPСервисОтвет.УстановитьТелоИзСтроки(
"{\"Статус\": \"Успех\", \"Сообщение\": \"Часть " + НомерЧасти + " принята.\"}",
"application/json", КодировкаТекста.UTF8
);
// Этап 3: Объединение после получения всех частей
// Эта логика может быть вызвана отдельным HTTP-запросом (например, "завершить загрузку")
// или автоматически после приема последней части.
// Проверяем, все ли части получены
СписокФайловЧастей = НайтиФайлы(ПутьКВременнойПапкеДляЗагрузки, "*.tmp");
Если СписокФайловЧастей.Количество() = ОбщееКоличествоЧастей Тогда
// Все части получены, приступаем к объединению
КоллекцияДвоичныхДанныхЧастей = Новый Массив;
Для Индекс = 1 По ОбщееКоличествоЧастей Цикл
ИмяТекущейЧасти = ПутьКВременнойПапкеДляЗагрузки + Формат(Индекс, "Ч(0,3,'0')") + ".tmp";
Если ФайлСуществует(ИмяТекущейЧасти) Тогда
КоллекцияДвоичныхДанныхЧастей.Добавить(Новый ДвоичныеДанные(ИмяТекущейЧасти));
Иначе
ВызватьИсключение "Не найдена часть файла #" + Индекс + " для сборки.";
КонецЕсли;
КонецЦикла;
// Объединяем все части в один объект ДвоичныеДанные
ИтоговыеДвоичныеДанные = Новый ДвоичныеДанные(КоллекцияДвоичныхДанныхЧастей);
// Дальнейшая логика сохранения ИтоговыеДвоичныеДанные через БСП
// ... (аналогично предыдущим примерам) ...
// После успешного сохранения, удаляем временную папку и части
УдалитьФайлы(ПутьКВременнойПапкеДляЗагрузки, "*.tmp");
УдалитьКаталог(ПутьКВременнойПапкеДляЗагрузки);
КонецЕсли;
В основе всех рассмотренных подходов лежит универсальный объект 1С - ДвоичныеДанные. Это ключевой объект платформы для работы с файлами и произвольными бинарными данными. Он доступен как на клиенте, так и на сервере, и предоставляет методы для:
ДвоичныеДанные в один (как показано в примере с частями).Мы используем его на протяжении всего процесса – от декодирования Base64-строки до получения тела HTTP-запроса и последующей передачи в функции БСП для сохранения.
В ходе обсуждения возник вопрос о "bin" как о специфическом формате файла. Важно понимать, что "Bin" (binary) — это не конкретный формат файла в том же смысле, что PDF, JPEG или DOCX. Это общий термин, обозначающий, что файл содержит двоичные данные. В контексте работы с файлами в 1С или передачи по сети, это означает, что содержимое файла представлено последовательностью байтов, а его интерпретация (как изображение, документ или что-либо еще) зависит от его фактического формата (определяемого внутренним строением файла и/или его расширением).
Как мы уже выяснили в ходе обсуждения, с точки зрения *передачи* бинарных данных через HTTP-сервис нет принципиальной разницы между PDF и JPEG файлами. Оба они являются наборами двоичных данных. Процесс кодирования (например, в Base64) и декодирования будет идентичным для обоих типов файлов. Различия заключаются только в их внутренней структуре и последующей *обработке* этих данных на стороне 1С или в другом приложении (например, для просмотра PDF требуется просмотрщик PDF, а для JPEG – просмотрщик изображений).
Выбор метода передачи сканов документов через HTTP-сервис в 1С зависит от нескольких факторов:
multipart/form-data.multipart/form-data или JSON с Base64 будут удобнее. Для прямой передачи метаданные придется размещать в заголовках HTTP-запроса или параметрах URL.multipart/form-data на стороне 1С требует более сложного ручного парсинга. Разделение файлов на части добавляет наибольшую сложность, но является единственным надежным решением для очень больших файлов.В любом случае, платформа 1С предоставляет все необходимые инструменты (Base64Значение(), Base64Строка(), ПолучитьТелоКакДвоичныеДанные(), объект ДвоичныеДанные, функционал БСП РаботаСФайлами.ДобавитьФайл) для успешной реализации каждого из этих подходов. Выбирайте тот метод, который наилучшим образом соответствует вашим требованиям к производительности, надежности и простоте интеграции.