Разработка и Конфигурация · 10 мин
Как получить файл из двоичных данных в 1С
Как получить файл из двоичных данных в 1С: методы Записать, ПолучитьИзВременногоХранилища, Base64. Примеры кода, проверка результата и типичные ошибки.
Двоичные данные в 1С встречаются повсюду: вложения писем, картинки номенклатуры, файлы в справочнике «Присоединенные файлы», ответы веб-сервисов, макеты типа «ДвоичныеДанные». Задача «получить из них обычный файл на диске» решается одним методом — Записать(), но на практике всё упирается в то, откуда именно берутся данные: из хранилища значений, временного хранилища, строки Base64 или реквизита объекта.
Ниже разобраны основные источники двоичных данных в платформе 1С:Предприятие, готовые фрагменты кода для клиент-серверного и файлового режима, способы проверить, что файл записался корректно, и типичные ошибки, из-за которых вместо документа получается битый файл нулевого размера.
Откуда могут приходить двоичные данные
Прежде чем писать код, определите источник данных — от этого зависит способ получения объекта ДвоичныеДанные. Сам объект универсален, но путь к нему различается.
- ХранилищеЗначения — типовой способ хранения файлов в реквизитах справочников и регистрах сведений. Извлекается методом
Получить(). - Временное хранилище — адрес вида
e1cib/tempstorage/..., в который помещаются данные при передаче между клиентом и сервером (загрузка файла, помещение картинки). - Строка Base64 — типичный формат передачи файлов через HTTP-сервисы, веб-сервисы и JSON.
- Макет конфигурации с типом «Двоичные данные» — готовые файлы, зашитые в конфигурацию.
- Поток / ПотокВПамяти — при работе с большими файлами и потоковой обработкой.
Базовый способ: метод Записать()
Если объект двоичных данных уже есть, сохранение файла занимает одну строку. Метод Записать() принимает полный путь к файлу, включая имя и расширение.
ДвоичныеДанные = Справочники.Макеты.НайтиПоКоду("Шаблон").Файл.Получить();
Если ДвоичныеДанные = Неопределено Тогда
ВызватьИсключение "Двоичные данные отсутствуют в хранилище значения";
КонецЕсли;
ИмяФайла = "C:\Temp\Шаблон.docx";
ДвоичныеДанные.Записать(ИмяФайла);
Обратите внимание: расширение файла платформа не восстанавливает автоматически. Если в хранилище лежит PDF, а вы записали его с расширением .txt, файл откроется некорректно. Расширение нужно хранить отдельно (в типовых конфигурациях для этого есть реквизит «Расширение» присоединённого файла) или определять по сигнатуре первых байт.
Каталог, в который пишется файл, должен существовать — метод Записать() не создаёт вложенные папки. Для служебных операций удобно использовать каталог временных файлов:
ИмяФайла = ПолучитьИмяВременногоФайла("pdf");
ДвоичныеДанные.Записать(ИмяФайла);
Получение данных из хранилища значений
Самый частый сценарий: файл лежит в реквизите типа ХранилищеЗначения. Например, нужно выгрузить все картинки номенклатуры в папку.
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Номенклатура.Ссылка,
| Номенклатура.ФайлКартинки
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ЭтоГруппа");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ДД = Выборка.ФайлКартинки.Получить();
Если ТипЗнч(ДД) = Тип("ДвоичныеДанные") Тогда
ДД.Записать("C:\Images\" + Строка(Выборка.Ссылка.УникальныйИдентификатор()) + ".jpg");
КонецЕсли;
КонецЦикла;
Ключевой момент — проверка типа после Получить(). Хранилище значений может содержать не только двоичные данные, но и Неопределено, картинку (Картинка) или другой сериализуемый объект. Вызов Записать() у значения Неопределено приведёт к ошибке выполнения.
- 1Определите источник данных: хранилище значения, временное хранилище, Base64 или макет
- 2Получите объект ДвоичныеДанные подходящим методом
- 3Проверьте, что полученное значение имеет тип ДвоичныеДанные
- 4Сформируйте полное имя файла с правильным расширением
- 5Вызовите Записать(ИмяФайла)
- 6Проверьте размер файла и его открытие в целевой программе
Работа с временным хранилищем
В управляемых формах файлы между клиентом и сервером передаются через временное хранилище. Типичная цепочка: пользователь выбрал файл на клиенте, данные помещены в хранилище, на сервере их нужно сохранить.
&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
НачатьПомещениеФайла(
Новый ОписаниеОповещения("ПослеПомещения", ЭтотОбъект),
, , Истина, УникальныйИдентификатор);
КонецПроцедуры
&НаСервере
Процедура СохранитьНаСервере(АдресХранилища)
ДД = ПолучитьИзВременногоХранилища(АдресХранилища);
ДД.Записать("C:\Temp\received.bin");
КонецПроцедуры
Обратная задача — отдать файл на клиент: поместите двоичные данные в хранилище через ПоместитьВоВременноеХранилище(ДД, УникальныйИдентификатор), а на клиенте используйте ПолучитьФайл() или НачатьПолучениеФайлов(). Для работы с файловой системой на тонком клиенте требуется расширение работы с файлами — без него методы записи на диск будут недоступны.
Двоичные данные из строки Base64
При обмене через HTTP и веб-сервисы файлы почти всегда передаются в кодировке Base64. Платформа предоставляет пару функций Base64Значение() и Base64Строка():
// Строка Base64 из тела HTTP-ответа или JSON
ДД = Base64Значение(СтрокаBase64);
ДД.Записать("C:\Temp\document.pdf");
// Обратное преобразование — файл в Base64 для отправки
ДД = Новый ДвоичныеДанные("C:\Temp\document.pdf");
СтрокаBase64 = Base64Строка(ДД);
Если Base64Значение() возвращает Неопределено, значит строка повреждена: потеряны символы, добавлены переносы в неправильных местах или данные обрезаны при чтении JSON. Проверьте длину строки и первые символы до преобразования.
Большие файлы и потоки
Для файлов значительного размера загрузка целиком в память через ДвоичныеДанные может быть нежелательна, особенно на сервере с несколькими сеансами. В таких случаях используйте файловые потоки:
Поток = ФайловыеПотоки.ОткрытьДляЗаписи("C:\Temp\big.zip");
ПотокИсточника.КопироватьВ(Поток);
Поток.Закрыть();
Потоковый подход также позволяет писать файл частями по мере получения данных из HTTP-ответа, не держа весь объём в памяти. Для типовых задач размером в несколько мегабайт обычного Записать() достаточно.
Проверка результата и типичные ошибки
После записи убедитесь, что файл корректен. Минимальная проверка — существование и ненулевой размер:
Файл = Новый Файл(ИмяФайла);
Если Не Файл.Существует() Или Файл.Размер() = 0 Тогда
ВызватьИсключение "Файл не записан или пуст";
КонецЕсли;
Дополнительно можно сверить размер записанного файла с размером двоичных данных (ДД.Размер()) — они должны совпадать. Для критичных обменов сравнивайте хеш-суммы до и после передачи.
Как проверить результат
Файл есть, размер больше 0 и равен размеру двоичных данных
Файл отсутствует или размер 0 байт
Документ/картинка/архив открывается без ошибок
Программа сообщает о повреждении или неверном формате
PDF начинается с %PDF, ZIP — с PK, JPEG — с FF D8
В начале виден текст Base64 или мусор
Частые вопросы
Как узнать расширение файла, если сохранены только двоичные данные?
По сигнатуре первых байт: PDF начинается с «%PDF», ZIP и DOCX/XLSX — с «PK», PNG — с байтов 89 50 4E 47, JPEG — с FF D8. Прочитайте начало данных и сопоставьте с известными сигнатурами. Надёжнее — хранить расширение отдельно при загрузке файла.
Метод Записать() выдаёт ошибку «Ошибка доступа к файлу». Что делать?
Проверьте, существует ли каталог, есть ли у учётной записи сервера 1С права на запись в него и не открыт ли файл другой программой. На сервере под Linux проверьте владельца каталога и права пользователя, под которым работает агент сервера.
Как получить файл из присоединённых файлов в типовой конфигурации?
В конфигурациях на БСП используйте функцию общего модуля РаботаСФайлами: она возвращает двоичные данные присоединённого файла по ссылке. Дальше применяется обычный Записать(). Прямой запрос к реквизиту хранения обходите, если доступен программный интерфейс БСП.
Можно ли записать файл на клиенте без модального окна сохранения?
Да, через ПолучитьФайл(АдресХранилища, ИмяФайла, Ложь) — третий параметр отключает диалог. Требуется расширение работы с файлами и разрешение пользователя на доступ к файловой системе в браузере или тонком клиенте.
Base64Значение() вернуло Неопределено. В чём причина?
Строка не является корректным Base64: лишние пробелы, переносы, обрезанный хвост или префикс вида «data:image/png;base64,». Удалите префикс до запятой и лишние символы, затем повторите преобразование.
Как выгрузить много файлов пакетно, не перегружая сервер?
Выполняйте выгрузку в фоновом задании, обрабатывайте записи порциями и записывайте каждый файл сразу после получения, не накапливая двоичные данные в памяти. Для очень больших файлов используйте потоки вместо объекта ДвоичныеДанные.
Что важно запомнить
Получение файла из двоичных данных сводится к трём шагам: получить объект ДвоичныеДанные подходящим способом (Получить, ПолучитьИзВременногоХранилища, Base64Значение), вызвать Записать() с корректным путём и расширением, затем проверить размер и открытие файла. Большинство проблем связаны с пустым хранилищем, неверным расширением и неправильной обработкой Base64.