Присоединённые файлы в БСП: получить, добавить и проверить программно
Содержимое присоединённого файла берётся одной строкой:
РаботаСФайлами.ДвоичныеДанныеФайла(ФайлСсылка). Для нескольких файлов есть
пакетный вариант ДвоичныеДанныеФайлов(Массив) — он возвращает
Соответствие «ссылка → двоичные данные» за один запрос.
Список файлов объекта заполняет ЗаполнитьПрисоединенныеФайлыКОбъекту(), новый файл
проще всего создать через ДобавитьФайлСДиска(), а перед добавлением стоит спросить
КОбъектуМожноПрисоединятьФайлы() — иначе получите исключение на определении
справочника хранения.
Где в БСП живут присоединённые файлы
Файлы хранятся в справочниках, а не в реквизитах объекта-владельца. Схема одинакова для всех конфигураций на БСП:
-
Владелец файлов — любой объект, тип которого входит в определяемый тип
ВладелецПрисоединенныхФайлов: документ, элемент справочника, папка файлов. -
Справочник хранения —
<ИмяВладельца>ПрисоединенныеФайлылибо общий справочникФайлы. Именно его элементы — присоединённые файлы. -
Определяемый тип
ПрисоединенныйФайл— объединение всех справочников хранения. По нему БСП проверяет входные параметры своих методов. -
Двоичные данные лежат отдельно: в регистре сведений
ХранилищеФайловлибо в томах на диске. Читать регистр напрямую не нужно — для этого есть публичные функции.
Весь программный интерфейс — в общем модуле РаботаСФайлами (серверный). Клиентские
команды живут в РаботаСФайламиКлиент, а всё, что с суффиксом
Служебный, — внутреннее и меняется между релизами БСП, опираться на него нельзя.
Как получить двоичные данные присоединённого файла
Базовая функция чтения — ДвоичныеДанныеФайла(). На вход ссылка на элемент справочника
с файлом, на выходе ДвоичныеДанные:
// Сохранение данных присоединённого файла на сервере
ДанныеФайла = РаботаСФайлами.ДвоичныеДанныеФайла(ФайлСсылка, Ложь);
Если ДанныеФайла <> Неопределено Тогда
ДанныеФайла.Записать("C:\Выгрузка\" + ФайлСсылка.Наименование + "." + ФайлСсылка.Расширение);
КонецЕсли;
Второй параметр решает судьбу сценария, когда данных нет ни в информационной базе, ни в томах.
При Истина (по умолчанию) будет исключение. При Ложь функция вернёт
Неопределено, а уровень записи в журнал регистрации понизится до «Предупреждение».
Для массовых выгрузок и фоновых заданий это ровно то, что нужно: один битый файл не должен ронять
обработку целиком.
Функция не отдаёт ни имени, ни расширения — только содержимое. Имя файла берут из реквизитов
Наименование и Расширение справочника хранения либо из структуры
ДанныеФайла().
Пакетное получение данных нескольких файлов
Вызывать ДвоичныеДанныеФайла() в цикле по сотне файлов — это сотня запросов к базе.
Для пачки есть отдельная функция, которая собирает всё одним запросом:
ФайлыДокумента = Новый Массив;
РаботаСФайлами.ЗаполнитьПрисоединенныеФайлыКОбъекту(ДокументСсылка, ФайлыДокумента);
// Один запрос на все файлы вместо цикла с обращениями к базе
ДанныеФайлов = РаботаСФайлами.ДвоичныеДанныеФайлов(ФайлыДокумента, Ложь);
Для Каждого КлючИЗначение Из ДанныеФайлов Цикл
ФайлСсылка = КлючИЗначение.Ключ;
ДвоичныеДанные = КлючИЗначение.Значение;
ЗаписьZip.Добавить(ДвоичныеДанные, ФайлСсылка.Наименование);
КонецЦикла;
Три особенности, которые видны только в коде модуля:
-
Однородность массива обязательна. Функция берёт тип первого элемента и сверяет
с ним остальные. Смешали
СправочникСсылка.ФайлыиСправочникСсылка.ЗаказКлиентаПрисоединенныеФайлы— получите исключение категории «ОшибкаКонфигурации». Разнотипные файлы разбивайте на пачки по типу. -
Пустой массив — не ошибка. Возвращается пустое
Соответствие, проверять количество перед вызовом не требуется. - Права проверяются на каждый файл. Файлы, недоступные текущему пользователю на чтение, в результат не попадают — и это не исключение, а молчаливое отсутствие записи.
Отсюда главное правило: количество записей в результате может быть меньше размера входного
массива. Обращаться к ДанныеФайлов[ФайлСсылка] без проверки на
Неопределено нельзя.
Список 1С БСП файлов, присоединённых к объекту
Искать файлы запросом по справочнику хранения не нужно: имя справочника зависит от типа владельца, а у одного владельца их может быть несколько. Готовый метод сам разберётся:
Файлы = Новый Массив; // массив создаём сами, процедура только дополняет его
РаботаСФайлами.ЗаполнитьПрисоединенныеФайлыКОбъекту(ДокументСсылка, Файлы);
Сообщить("Присоединено файлов: " + Файлы.Количество());
Это процедура, а не функция: она добавляет ссылки в переданный массив, не очищая его. Удобно для сбора файлов сразу по нескольким объектам в один список — достаточно вызвать её в цикле с тем же массивом.
Если владелец не заполнен или это ссылка на
Справочник.ИдентификаторыОбъектовМетаданных, процедура тихо выходит, оставив массив
как есть. Пустой результат поэтому означает и «файлов нет», и «передали пустую ссылку».
Как добавить присоединённый файл с диска
Самый короткий путь создать файл — ДобавитьФайлСДиска(). Функция сама читает файл,
помещает данные во временное хранилище, извлекает текст и создаёт элемент справочника хранения:
// Файл должен лежать на сервере 1С, не на клиенте
ФайлСсылка = РаботаСФайлами.ДобавитьФайлСДиска(ДокументСсылка, "/opt/exchange/act-1024.pdf");
Сообщить("Создан файл: " + Строка(ФайлСсылка));
Имя и расширение берутся из самого пути, поэтому переименовать файл на лету здесь нельзя — для
этого нужен ДобавитьФайл() с явными параметрами. Если справочник хранения поддерживает
версии (типовой Справочник.Файлы), сразу создаётся первая версия.
Пустой ВладелецФайлов — исключение категории «ОшибкаКонфигурации» с явным текстом про
незаполненный параметр. Извлечение текста зависит от настроек базы: при серверном извлечении его
сделает регламентное задание позже, иначе на Windows-сервере текст извлекается тут же.
Устаревший аналог СоздатьФайлНаОсновеФайлаНаДиске() в новом коде не используют — он
просто переадресует вызов в ДобавитьФайлСДиска().
Новая ссылка на файл и добавление данных из памяти
Когда данные не лежат на диске, а формируются в коде (печатная форма, ответ HTTP-сервиса,
выгрузка), файл добавляют из временного хранилища. Ссылку на будущий элемент справочника выдаёт
НоваяСсылкаНаФайл():
СсылкаНаФайл = РаботаСФайлами.НоваяСсылкаНаФайл(ДокументСсылка);
Адрес = ПоместитьВоВременноеХранилище(ДвоичныеДанныеПечатнойФормы, Новый УникальныйИдентификатор);
ПараметрыФайла = РаботаСФайлами.ПараметрыДобавленияФайла();
ПараметрыФайла.ВладелецФайлов = ДокументСсылка;
ПараметрыФайла.ИмяБезРасширения = "Акт сверки";
ПараметрыФайла.РасширениеБезТочки = "pdf";
ПараметрыФайла.ВремяИзмененияУниверсальное = ТекущаяУниверсальнаяДата();
ФайлСсылка = РаботаСФайлами.ДобавитьФайл(ПараметрыФайла, Адрес, "", "Акт сверки за период", СсылкаНаФайл);
Смысл предварительной ссылки — знать идентификатор файла до его записи: положить его в регистр,
в лог обмена или в ответ веб-сервиса. Если у владельца несколько справочников хранения, вычислить
его автоматически нельзя — ИмяСправочника становится обязательным, иначе будет
исключение.
// Тот же вызов, когда справочник хранения задан явно
СсылкаНаФайл = РаботаСФайлами.НоваяСсылкаНаФайл(ДокументСсылка, "ЗаказКлиентаПрисоединенныеФайлы");
Расширение можно не указывать отдельно: если РасширениеБезТочки пустое, а в
ИмяБезРасширения есть точка, БСП отрежет расширение сама. Флаг
Служебный скрывает файл от пользователя в интерфейсе — им помечают технические
вложения обменов.
Проверка: можно ли присоединять файлы к объекту
Универсальный код (обработка обмена, подписка, общий сервис) не знает заранее, поддерживает ли конкретный тип владельца присоединённые файлы. Проверка — одна функция, без исключений:
Если РаботаСФайлами.КОбъектуМожноПрисоединятьФайлы(ОбъектСсылка) Тогда
РаботаСФайлами.ДобавитьФайлСДиска(ОбъектСсылка, ПутьКФайлу);
Иначе
ЗаписьЖурналаРегистрации("Обмен.Файлы", УровеньЖурналаРегистрации.Предупреждение,,,
"К объекту нельзя присоединять файлы: " + Строка(ТипЗнч(ОбъектСсылка)));
КонецЕсли;
Функция возвращает Истина только при совпадении четырёх условий: справочник хранения
существует в конфигурации, у пользователя есть право Добавление на него,
справочник входит в определяемый тип ПрисоединенныйФайл и сам владелец не является
присоединённым файлом. Последнее отсекает попытки прикрепить файл к файлу.
Обратите внимание: право доступа входит в проверку. Один и тот же объект даст
Истина администратору и Ложь пользователю с урезанной ролью — это
штатное поведение, а не ошибка конфигурации.
Обновить данные существующего присоединённого файла
Перезаписать содержимое файла присваиванием реквизита нельзя: двоичные данные лежат в отдельном
регистре или в томе. Для файлов без версий есть ОбновитьФайл():
ИнформацияОФайле = Новый Структура;
ИнформацияОФайле.Вставить("АдресФайлаВоВременномХранилище", ПоместитьВоВременноеХранилище(НовыеДанные));
ИнформацияОФайле.Вставить("АдресВременногоХранилищаТекста", ""); // свойство обязательно, даже пустое
ИнформацияОФайле.Вставить("ИмяБезРасширения", "Акт сверки (исправленный)");
ИнформацияОФайле.Вставить("Расширение", "pdf");
РаботаСФайлами.ОбновитьФайл(ФайлСсылка, ИнформацияОФайле);
Метод работает в транзакции с управляемой блокировкой элемента справочника, поэтому вызывать его
внутри своей длинной транзакции не стоит. Два адреса временного хранилища читаются из структуры
напрямую — если свойств нет, будет ошибка обращения к несуществующему свойству, а не понятное
сообщение. Остальные свойства проверяются через Свойство() и потому необязательны.
Дата модификации ведёт себя нестандартно: по умолчанию ставится текущая универсальная дата, а переданное значение применяется, только если оно меньше текущей. Будущей датой файл пометить не получится. Для файлов с версиями метод не предназначен — там версия добавляется средствами подсистемы версионирования.
Сведения о файле: ДанныеФайла вместо чтения реквизитов
Когда нужны не только байты, а имя, размер, признаки подписи и шифрования, автор и адрес данных во
временном хранилище, используют ДанныеФайла(). Она возвращает структуру, которую
остальные методы подсистемы принимают как готовый параметр:
ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
ПараметрыДанныхФайла.ИдентификаторФормы = УникальныйИдентификатор;
ПараметрыДанныхФайла.ВызыватьИсключение = Ложь;
Сведения = РаботаСФайлами.ДанныеФайла(ФайлСсылка, ПараметрыДанныхФайла);
Если Сведения <> Неопределено Тогда
Сообщить(Сведения.ИмяФайла + ", " + Сведения.Размер + " байт, подписан: " + Сведения.ПодписанЭП);
КонецЕсли;
В структуре среди прочего есть Ссылка, Владелец,
ИмяФайла, Расширение, Размер,
ДатаМодификацииУниверсальная, ПодписанЭП, Зашифрован,
ПометкаУдаления, ТекущаяВерсия, НомерВерсии,
Том, Автор и СсылкаНаДвоичныеДанныеФайла — адрес данных во
временном хранилище.
Важный побочный эффект: при ДляРедактирования = Истина файл занимается текущим
пользователем — это интерактивный сценарий. Для фоновой обработки этот флаг не включают, иначе
файлы останутся заблокированными.
РаботаСФайлами и выполнит его на вашей базе, показав
результат: не придётся вручную сверять имена справочников хранения и состав параметров.
Частые ошибки при работе с присоединёнными файлами БСП
-
Разнотипные файлы в
ДвоичныеДанныеФайлов(). Все элементы массива должны быть одного типа справочника хранения. Иначе — исключение категории «ОшибкаКонфигурации». Группируйте файлы поТипЗнч()перед вызовом. -
Результат пакетной функции считают полным. Файлы без прав на чтение и файлы
с отсутствующими двоичными данными (при
ВызыватьИсключение = Ложь) вСоответствиене попадают. Проверяйте наличие ключа, а не индекс массива. -
Массив не создан перед
ЗаполнитьПрисоединенныеФайлыКОбъекту(). Это процедура: она дополняет переданную коллекцию, но не создаёт её и не чистит. Повторный вызов с тем же массивом накапливает дубли. -
Путь к файлу в
ДобавитьФайлСДиска()— клиентский. Файл читается на сервере 1С. Локальный путь пользователя в клиент-серверной базе даст ошибку открытия файла; данные с клиента передавайте через временное хранилище иДобавитьФайл(). -
Несколько справочников хранения у владельца. Тогда
НоваяСсылкаНаФайл()иДобавитьФайл()без явного имени справочника (или без параметраНоваяСсылкаНаФайл) выбрасывают исключение — определить хранилище автоматически невозможно. -
Неполная структура в
ОбновитьФайл(). СвойстваАдресФайлаВоВременномХранилищеиАдресВременногоХранилищаТекстачитаются напрямую и обязательны, второе — хотя бы пустой строкой. -
Размер файла больше допустимого. Ограничение возвращает
РаботаСФайлами.МаксимальныйРазмерФайла()(по умолчанию 50 МБ). Проверяйте его до добавления, а не после падения записи. -
Вызов служебных модулей.
РаботаСФайламиСлужебныйиРаботаСФайламиСлужебныйВызовСервера— внутренние. Их состав меняется при обновлении БСП, обращаться к ним из прикладного кода нельзя.
Частые вопросы о присоединённых файлах в БСП
Как получить двоичные данные присоединённого файла в БСП?
Вызвать РаботаСФайлами.ДвоичныеДанныеФайла(ФайлСсылка) — вернутся
ДвоичныеДанные независимо от того, лежит файл в информационной базе или в томе.
Со вторым параметром Ложь вместо исключения вернётся Неопределено,
что удобно для массовых выгрузок.
Как программно добавить файл к объекту в 1С на БСП?
Файл с диска сервера — РаботаСФайлами.ДобавитьФайлСДиска(Владелец, Путь). Данные
из памяти — ПоместитьВоВременноеХранилище(), затем
ДобавитьФайл() со структурой из ПараметрыДобавленияФайла(). Перед
добавлением стоит проверить КОбъектуМожноПрисоединятьФайлы().
Почему ДвоичныеДанныеФайлов возвращает меньше записей, чем передано файлов?
Функция пропускает файлы, недоступные пользователю на чтение, и файлы без двоичных данных,
если вызвана с ВызыватьИсключение = Ложь. Результат — это
Соответствие, а не массив: перебирайте его циклом либо проверяйте ключ на
Неопределено.
ИИ Консоль кода 1С
Лайт
Для ознакомления с возможностями
- Полный набор инструментов без урезаний
- Без ввода карты
Старт
Для индивидуального использования
- До 5 конфигураций
- Встроенный агент запросов 1С
-
≈ 100 задач Подробнее про лимиты
- Техническая поддержка
Продвинутый
Популярный выборДля интенсивного использования или команд
- До 15 конфигураций
- Встроенный агент запросов 1С
-
≈ 300 задач Подробнее про лимиты
-
Свои подписки Codex, Claude и любые OpenAI-совместимые
-
Внешние обработки без Конфигуратора
- Приоритетная техническая поддержка