К статье
Практический материал

Разработка и Конфигурация · 10 мин

Чтение файла как двоичных данных в 1С

Как в 1С прочитать файл как двоичные данные: объект ДвоичныеДанные, чтение с диска, из хранилища значений, Base64, примеры кода и типичные ошибки.

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

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

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

Базовый способ: конструктор «Новый ДвоичныеДанные»

Самый простой и самый частый вариант — передать путь к файлу в конструктор объекта ДвоичныеДанные. Платформа прочитает файл целиком и вернёт объект, с которым можно работать дальше.

ДвоичныеДанные = Новый ДвоичныеДанные("C:\Обмен\invoice.pdf");

Сообщить("Размер файла: " + ДвоичныеДанные.Размер() + " байт");

Метод Размер() возвращает размер данных в байтах — это удобный способ проверить, что файл прочитался не пустым. Если файл не существует или недоступен по указанному пути, платформа выбросит исключение, поэтому в реальном коде чтение стоит оборачивать в Попытка...Исключение или предварительно проверять существование файла.

Важный нюанс: конструктор выполняется там, где выполняется код. Если код работает на сервере 1С, путь должен быть доступен именно с сервера — локальный диск клиентской машины сервер не увидит. Это самая частая причина ошибки «файл не обнаружен» в клиент-серверном режиме.

Чтение файла на клиенте и передача на сервер

В управляемом приложении файл обычно выбирает пользователь на своём компьютере, а обработка происходит на сервере. Прямого чтения с клиентского диска на сервере нет, поэтому используется механизм временного хранилища: клиент помещает файл, получает адрес, а сервер забирает данные по этому адресу.

Асинхронное помещение файла

В современных версиях платформы модальные и синхронные вызовы работы с файлами запрещены или нежелательны, поэтому используется асинхронный метод НачатьПомещениеФайла с описанием оповещения.

&НаКлиенте

Процедура ЗагрузитьФайл(Команда)

ОписаниеОповещения = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);

НачатьПомещениеФайла(ОписаниеОповещения, , , Истина, УникальныйИдентификатор);

КонецПроцедуры

&НаКлиенте

Процедура ПослеПомещенияФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт

Если Результат Тогда

ОбработатьФайлНаСервере(Адрес);

КонецЕсли;

КонецПроцедуры

&НаСервереБезКонтекста

Процедура ОбработатьФайлНаСервере(Адрес)

ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес);

// дальше работаем с ДвоичныеДанные

КонецПроцедуры

Параметр Истина в НачатьПомещениеФайла включает диалог выбора файла. Если путь уже известен (например, файл сформирован на клиенте программно), диалог можно не показывать и передать путь вторым параметром.

Проверка результата

Признак успешного чтения — объект типа ДвоичныеДанные с размером больше нуля. Если ПолучитьИзВременногоХранилища вернуло строку или Неопределено, значит файл не был помещён: пользователь отменил диалог, адрес хранилища устарел или помещение выполнялось в другом сеансе.

Контрольные точки

Как проверить результат

Тип значения после ПолучитьИзВременногоХранилища
Норма

Тип ДвоичныеДанные

Тревожный признак

Строка с адресом или Неопределено — файл не помещён

Размер данных
Норма

Размер() больше нуля и совпадает с размером файла на диске

Тревожный признак

Ноль байт — прочитан пустой или несуществующий файл

Работа в веб-клиенте
Норма

Установлено расширение работы с файлами

Тревожный признак

Ошибка при вызове методов работы с файлами

Чтение через потоки

Начиная с версии платформы 8.3.11, для работы с файлами доступны потоки. Они нужны, когда файл большой, когда данные приходят из сети, или когда нужно читать только часть файла, а не загружать всё в память.

Поток = ФайловыеПотоки.ОткрытьДляЧтения("C:\Обмен\bigdata.zip");

ПотокВывода = ПотокиВПамяти.Создать();

Поток.КопироватьВ(ПотокВывода);

ДвоичныеДанные = ПотокВывода.ЗакрытьИПолучитьДвоичныеДанные();

Поток.Закрыть();

Для небольших файлов потоки избыточны — конструктор Новый ДвоичныеДанные проще и читаемее. Но при размере в сотни мегабайт потоковая обработка снижает пиковое потребление памяти и позволяет читать файл порциями через БуферДвоичныхДанных.

Отдельный сценарий — чтение части файла. Метод Поток.Перейти(Смещение, ПозицияВПотоке.Начало) позволяет сместиться на нужный байт и прочитать только требуемый фрагмент, что полезно при разборе заголовков файлов без загрузки всего содержимого.

Двоичные данные из хранилища значений и реквизитов

Файлы, хранящиеся в базе (вложения, картинки, печатные формы), обычно лежат в реквизитах типа ХранилищеЗначения. Чтобы получить двоичные данные, значение нужно извлечь методом Получить().

Запрос = Новый Запрос("ВЫБРАТЬ Файл ИЗ Справочник.ПрисоединенныеФайлы ГДЕ Ссылка = &Ссылка");

Запрос.УстановитьПараметр("Ссылка", ФайлСсылка);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

ДвоичныеДанные = Выборка.Файл.Получить();

КонецЕсли;

Метод Получить() возвращает значение, которое было помещено в хранилище, — обычно это именно ДвоичныеДанные, но встречаются конфигурации, где хранится строка Base64 или структура. Перед использованием полезно проверить тип через ТипЗнч().

В типовых конфигурациях (БСП) для работы с присоединёнными файлами есть готовые процедуры модуля РаботаСФайлами, которые уже возвращают двоичные данные. Если база построена на БСП, писать собственные запросы к служебным справочникам обычно не нужно.

Преобразование в Base64 и обратно

Двоичные данные нельзя напрямую вставить в JSON, XML-атрибут или строку запроса — для текстового представления используется кодировка Base64. В платформе для этого есть две пары функций: Base64Строка() / Base64Значение() и XMLСтрока() / XMLЗначение().

// Кодирование

СтрокаBase64 = Base64Строка(ДвоичныеДанные);

// Декодирование обратно в двоичные данные

ДвоичныеДанные = Base64Значение(СтрокаBase64);

Помните, что Base64 увеличивает объём данных примерно на треть. Для файла в 30 МБ строка займёт около 40 МБ в памяти, что при массовой обработке может привести к переполнению памяти сервера. Для крупных вложений лучше передавать данные через тело HTTP-запроса напрямую, без промежуточного кодирования в строку.

Запись двоичных данных обратно в файл

Обратная операция выполняется методом Записать(ИмяФайла). Это стандартный способ сохранить на диск вложение из письма, файл из хранилища или данные, полученные по HTTP.

ДвоичныеДанные.Записать("C:\Обмен\полученный_файл.xlsx");

Перед записью убедитесь, что каталог существует — платформа не создаёт недостающие папки автоматически. Также учитывайте права: на сервере запись выполняется от имени учётной записи агента сервера 1С, и у неё должен быть доступ к целевому каталогу.

Типичные ошибки
01
Чтение клиентского файла на сервере — сервер не видит диски пользователя, нужно временное хранилище
02
Отсутствие проверки существования файла — любой сбой пути приводит к необработанному исключению
03
Забытый Получить() у хранилища значения — в переменной остаётся ХранилищеЗначения, а не ДвоичныеДанные
04
Кодирование большого файла в Base64 в цикле — резкий рост потребления памяти и падение рабочего процесса
05
Использование устаревших синхронных методов ПоместитьФайл в конфигурациях с запретом модальности — код не компилируется или не работает в веб-клиенте

Выбор способа под конкретную задачу

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

Маршрут решения

Как выбрать действие

Файл лежит на сервере, размер умеренныйИспользуйте Новый ДвоичныеДанные(Путь)
Файл выбирает пользователь на клиентеНачатьПомещениеФайла на клиенте, ПолучитьИзВременногоХранилища на сервере
Файл очень большой или нужен фрагментЧитайте через ФайловыеПотоки и буферы
Нужно передать данные строкой в JSON или XMLКодируйте через Base64Строка, принимайте через Base64Значение
Файл хранится в базеИзвлеките значение реквизита ХранилищеЗначения методом Получить()
Итог

Что важно запомнить

Основной инструмент — конструктор Новый ДвоичныеДанные(Путь). Клиентские файлы сначала помещаются во временное хранилище, большие файлы читаются потоками, а для текстовой передачи данные кодируются в Base64. Всегда проверяйте существование файла, тип полученного значения и размер данных.

Частые вопросы

Можно ли прочитать файл как двоичные данные в веб-клиенте?

Да, но только через асинхронные методы помещения файла во временное хранилище и при установленном расширении работы с файлами в браузере. Прямой вызов Новый ДвоичныеДанные с локальным путём в веб-клиенте недоступен.

Как узнать размер файла до чтения?

Используйте объект Файл: Ф = Новый Файл(Путь); Если Ф.Существует() Тогда Размер = Ф.Размер();. Это позволяет проверить существование файла и оценить объём до загрузки в память.

Чем ДвоичныеДанные отличаются от объекта ЧтениеДанных?

ДвоичныеДанные — неизменяемый объект с готовым содержимым файла. ЧтениеДанных — последовательный читатель, который позволяет разбирать файл по частям: читать байты, числа и строки с указанием позиции. Для разбора форматов файлов удобнее второй вариант.

Почему Base64Значение возвращает ошибку или пустые данные?

Чаще всего строка содержит переносы строк, пробелы или префикс вида data:image/png;base64,, который нужно отрезать. Также функция чувствительна к повреждённым символам — строка должна быть валидным Base64.

Можно ли изменить часть двоичных данных без перезаписи всего объекта?

Нет, объект неизменяем. Нужно получить данные в поток или БуферДвоичныхДанных, внести изменения и сформировать новый объект ДвоичныеДанные из результата.

Как передать двоичные данные между сеансами или в фоновое задание?

Напрямую в параметры фонового задания двоичные данные передавать нельзя. Стандартный приём — поместить их во временное хранилище и передать в задание адрес, а внутри задания получить данные по этому адресу.