Разработка и Конфигурация · 12 мин
Как двоичные данные преобразовать в файл в 1С
Как преобразовать двоичные данные в файл 1С: метод Записать, Base64, временные файлы, работа с хранилищем значений. Примеры кода, ошибки и проверка результата.
Задача преобразования двоичных данных в файл возникает в 1С постоянно: выгрузка картинок из хранилища значений, сохранение вложений из почты, запись ответа веб-сервиса, восстановление файлов из архивных копий. Во всех этих случаях у вас есть объект типа ДвоичныеДанные, который нужно материализовать на диск в виде обычного файла — с правильным расширением, кодировкой и содержимым.
Встроенный язык платформы предоставляет для этого несколько инструментов: метод Записать объекта ДвоичныеДанные, работу через потоки, преобразование из строки Base64 и механизм временных файлов. Выбор зависит от того, откуда данные получены, где должен оказаться файл — на клиенте или на сервере — и насколько велик объём.
Ошибки в этой операции обычно незаметны сразу: файл создаётся, но оказывается пустым, битым или с неверной кодировкой. Поэтому важно не только записать данные, но и проверить результат — размер, читаемость, соответствие исходнику. Ниже разобраны рабочие способы с примерами кода и типичными проблемами.
Что такое двоичные данные в 1С и откуда они берутся
ДвоичныеДанные — это примитивный тип платформы, представляющий последовательность байт без интерпретации. Внутри может лежать что угодно: картинка, PDF-документ, zip-архив, XML, исполняемый файл. Платформа не знает формата — расширение и структуру определяете вы при записи.
Типичные источники двоичных данных в прикладном коде: реквизиты типа ХранилищеЗначения в справочниках и документах, чтение файлов методом Новый ДвоичныеДанные(Путь), ответы HTTP-соединений, вложения электронной почты, поля BLOB при обмене с внешними базами. Часто данные приходят в виде строки Base64 — например, из JSON веб-сервисов.
Базовый способ: метод Записать
Основная операция выглядит предельно просто — у объекта ДвоичныеДанные есть метод Записать, принимающий полное имя файла:
ДвоичныеДанные = Справочники.Файлы.НайтиПоКоду("000001").Файл.Получить();
ДвоичныеДанные.Записать("C:\Temp\Отчет.pdf");
Здесь сначала из реквизита типа ХранилищеЗначения извлекается значение методом Получить — в нашем случае это объект ДвоичныеДанные. Затем он записывается по указанному пути. Если файл с таким именем существует, он будет перезаписан без предупреждения.
Критически важно указывать правильное расширение. Платформа не анализирует содержимое: если записать PDF под именем «документ.txt», файл физически останется PDF, но операционная система и пользователь будут пытаться открыть его как текст. Расширение лучше хранить отдельно рядом с двоичными данными — например, в реквизите справочника присоединённых файлов.
Обратите внимание на контекст выполнения: в серверном коде файл создаётся на сервере 1С, а не на компьютере пользователя. Путь "C:\Temp" в серверной процедуре указывает на диск сервера. Это самая частая причина вопроса «код отработал, а файла нет».
Запись файла на клиенте и передача с сервера
В файловом режиме клиент и сервер совпадают, и проблем нет. В клиент-серверном варианте типовая схема такая: серверная процедура готовит двоичные данные и помещает их во временное хранилище, клиентский код забирает данные по адресу и сохраняет локально.
&НаСервере
Функция ПодготовитьФайлНаСервере(СсылкаНаФайл)
Данные = СсылкаНаФайл.Данные.Получить();
Возврат ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификаторФормы);
КонецФункции
&НаКлиенте
Процедура СохранитьФайл(Команда)
Адрес = ПодготовитьФайлНаСервере(ТекущийФайл);
Данные = ПолучитьИзВременногоХранилища(Адрес);
Данные.Записать("C:\Users\User\Documents\Выгрузка.xlsx");
КонецПроцедуры
В тонком и веб-клиенте синхронные методы работы с файловой системой могут быть недоступны или требовать расширения работы с файлами. Тогда используют асинхронный вариант — метод НачатьЗапись с описанием оповещения, либо диалог выбора файла через ДиалогВыбораФайла, чтобы пользователь сам указал, куда сохранить результат.
Для веб-клиента альтернатива — функция ПолучитьФайл(Адрес, ИмяФайла, Истина): данные из временного хранилища будут переданы пользователю как скачивание через браузер. Это самый надёжный путь, когда нет гарантий, что у клиента установлено расширение работы с файлами.
- 1В серверной процедуре получите двоичные данные из хранилища значений или другого источника
- 2Поместите данные во временное хранилище с привязкой к УникальныйИдентификаторФормы
- 3Верните адрес хранилища в клиентский код
- 4На клиенте получите данные из хранилища и запишите методом Записать или передайте через ПолучитьФайл
- 5Проверьте, что файл создан и его размер больше нуля
Преобразование из строки Base64 и обратно
При обмене через веб-сервисы и JSON двоичные данные почти всегда передаются в кодировке Base64 — это текстовое представление байт. Перед записью в файл такую строку нужно преобразовать обратно:
ДвоичныеДанные = Base64Значение(СтрокаИзJSON);
ДвоичныеДанные.Записать(ИмяФайла);
Обратное преобразование — функция Base64Строка(ДвоичныеДанные) — нужно, когда вы отправляете файл наружу. Помните, что Base64 увеличивает объём данных примерно на треть, поэтому большие файлы через JSON передавать накладно.
Частая ловушка — лишние символы в строке Base64: переносы строк, префиксы вида data:image/png;base64,, пробелы. Функция Base64Значение может выдать ошибку или вернуть некорректные данные. Перед преобразованием очищайте строку: отсекайте префикс до запятой и удаляйте символы переноса функцией СтрЗаменить.
// Очистка и преобразование Base64
Строка = СтрЗаменить(Строка, "data:image/png;base64,", "");
Строка = СтрЗаменить(Строка, Символы.ПС, "");
Строка = СтрЗаменить(Строка, Символы.ВК, "");
Данные = Base64Значение(Строка);
Данные.Записать(ИмяФайла);Работа с большими файлами и временными файлами
Когда объём данных велик — сотни мегабайт — держать их целиком в памяти нежелательно, особенно на сервере, где один сеанс может отнять ресурсы у других пользователей. Для таких случаев платформа предоставляет потоки: объекты Поток, ПотокВПамяти, ФайловыйПоток и менеджеры чтения/записи данных (ЧтениеДанных, ЗаписьДанных).
Типовой приём — получить поток из двоичных данных методом ОткрытьПотокДляЧтения и копировать его в файловый поток порциями. Это снижает пиковое потребление памяти и позволяет обрабатывать файлы, которые не поместились бы в оперативную память целиком.
Для промежуточных операций используйте временные файлы: функция ПолучитьИмяВременногоФайла("zip") вернёт уникальное имя в каталоге временных файлов. Это защищает от коллизий имён при параллельной работе пользователей. После использования временные файлы стоит удалять явно методом УдалитьФайлы — платформа не всегда очищает их автоматически, и каталог temp на сервере со временем разрастается.
Проверка результата и типичные ошибки
Успешное выполнение метода Записать не гарантирует корректность файла. Минимальная проверка — существование файла и его размер через объект Файл: размер не должен быть нулевым и должен совпадать с размером исходных данных (метод Размер у ДвоичныеДанные). Для критичных обменов сверяют контрольные суммы, если внешняя система их передаёт.
Как проверить результат
Объект Файл найден по указанному пути, Существует() = Истина
Файл отсутствует — вероятно, запись шла на другой стороне (сервер/клиент перепутаны)
Размер больше нуля и равен размеру исходных двоичных данных
Нулевой размер — данные не извлечены из хранилища (Получить вернул Неопределено)
Файл открывается штатной программой без ошибок
Программа сообщает о повреждении — неверное преобразование Base64 или обрезка данных
Теперь разберём ошибки, которые встречаются чаще всего. Первая — запись Неопределено: если реквизит хранилища значений пуст, метод Получить вернёт Неопределено, и попытка вызвать Записать вызовет исключение. Всегда проверяйте результат Получить перед записью.
Вторая группа ошибок — права доступа. На сервере код выполняется под учётной записью службы агента 1С, у которой может не быть прав на произвольные каталоги. Используйте выделенную папку с явно выданными правами на запись. Третья типичная проблема — отсутствие расширения или его несоответствие содержимому, из-за чего пользователь не может открыть файл двойным щелчком.
Выбор способа под конкретную задачу
Для разовой выгрузки из хранилища значений в файловой базе достаточно Получить + Записать. Для клиент-серверного режима с интерактивным сохранением — временное хранилище плюс ПолучитьФайл или диалог сохранения. Для обмена с внешними API — Base64Значение с предварительной очисткой строки. Для больших файлов и пакетной обработки — потоки и файловые потоки.
Сравнение вариантов
Подходит для файлового режима и серверного кода. Простейший код, но файл окажется там, где выполняется процедура
Стандарт для клиент-серверного режима и веб-клиента: пользователь получает файл как скачивание. Требует передачи адреса хранилища
Нужен при обмене через JSON и веб-сервисы. Требует очистки строки от префиксов и переносов
Для больших файлов и пакетной обработки. Сложнее код, но контролируемое потребление памяти
Если сомневаетесь в выборе, ориентируйтесь на два вопроса: где должен оказаться файл (клиент или сервер) и каков ожидаемый объём. Ответы на них однозначно определяют схему.
Как выбрать действие
Частые вопросы
Почему метод Записать отработал без ошибок, но файла нет?
Чаще всего код выполнился на сервере, а файл ищут на клиентском компьютере. Проверьте директиву компиляции процедуры (&НаСервере или &НаКлиенте) и посмотрите каталог на соответствующей машине. Также убедитесь, что путь существует — платформа не создаёт промежуточные каталоги автоматически.
Как записать файл, если данные хранятся в справочнике как ХранилищеЗначения?
Вызовите метод Получить() у реквизита — он вернёт сохранённое значение. Если это объект ДвоичныеДанные, запишите его методом Записать. Обязательно проверьте результат на Неопределено: пустое хранилище вернёт именно его, и попытка записи вызовет ошибку.
Файл после записи не открывается, программа пишет «файл повреждён». В чём причина?
Типичные причины: строка Base64 содержала префикс вида data:image/png;base64, или переносы строк, данные были обрезаны при передаче, либо записана не та сущность (например, строка вместо двоичных данных). Сравните размер полученного файла с размером исходных данных — расхождение укажет на потерю байт.
Можно ли записать двоичные данные в файл в веб-клиенте?
Напрямую в произвольный путь — нет, браузер ограничивает доступ к файловой системе. Рабочий вариант: поместить данные во временное хранилище на сервере и вызвать на клиенте ПолучитьФайл(Адрес, ИмяФайла, Истина) — пользователь получит файл через механизм скачивания браузера.
Как правильно удалять временные файлы после использования?
Используйте метод УдалитьФайлы(Путь) с отбором по маске или УдалитьФайлы для конкретного имени. Удаление лучше обернуть в попытку/исключение: файл может быть занят другим процессом. На сервере полезна периодическая регламентная очистка каталога временных файлов, так как аварийные завершения сеансов оставляют мусор.
Что важно запомнить
Двоичные данные преобразуются в файл методом Записать, строка Base64 — через Base64Значение с предварительной очисткой. Контролируйте контекст выполнения (сервер или клиент), проверяйте результат Получить() на Неопределено, указывайте корректное расширение и сверяйте размер записанного файла с исходным. Для клиент-серверного режима и веб-клиента используйте временное хранилище и ПолучитьФайл, для больших объёмов — потоки.