В процессе разработки расширений или автоматизации в VS Code для 1С:Документооборот часто возникает задача массовой выгрузки присоединенных файлов. Типовой функционал системы позволяет сохранять файлы, но иногда требуется специфическая логика: например, распределить файлы по папкам, соответствующим кодам или номерам документов, и одновременно выгрузить связанные реквизиты или экспортировать печатные формы. В этой статье мы подробно разберем, как реализовать такую выгрузку максимально эффективно, используя механизмы платформы 1С:Предприятие 8.3 и возможности Библиотеки стандартных подсистем (БСП).
Представим ситуацию: нам необходимо выгрузить все файлы по определенному виду документа за выбранный период. При этом файлы не должны сваливаться в «братскую могилу» (одну общую папку), а должны быть аккуратно разложены по подкаталогам, именованным согласно кодам внутренних документов. Рассмотрим, почему стандартные циклы с использованием НачатьПолучениеФайлаССервера (в единственном числе) проигрывают пакетному методу.
Основная проблема при поштучном получении файлов заключается в многократных вызовах между клиентом и сервером, что существенно замедляет работу при больших объемах данных. Оптимальным решением является использование метода НачатьПолучениеФайловССервера, который позволяет передать массив описаний файлов и загрузить их одной операцией.
Для начала нам необходимо собрать список документов и получить двоичные данные присоединенных к ним файлов. Проанализируем серверную функцию, которая формирует массив объектов ОписаниеПередаваемогоФайла. Обратите внимание на использование временного хранилища — это ключевой момент для передачи данных с сервера на клиент.
Разберем пример серверной функции:
&НаСервере
Функция ПодготовитьМассивФайловДляВыгрузки() Экспорт
МассивРезультат = Новый Массив;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВнутренниеДокументы.Ссылка КАК Ссылка,
| ВнутренниеДокументы.Код КАК Код
|ИЗ
| Справочник.ВнутренниеДокументы КАК ВнутренниеДокументы
|ГДЕ
| ВнутренниеДокументы.ВидДокумента = &ВидДокумента";
Запрос.УстановитьПараметр("ВидДокумента", Объект.ВидДокумента);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Получаем все файлы, присоединенные к документу
СписокФайлов = РаботаСФайламиСлужебный.ВсеПодчиненныеФайлы(Выборка.Ссылка);
Для Каждого СсылкаНаФайл Из СписокФайлов Цикл
Если СсылкаНаФайл.ПометкаУдаления Тогда
Продолжить;
КонецЕсли;
// Получаем двоичные данные файла через методы БСП
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(СсылкаНаФайл);
// Помещаем данные во временное хранилище
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
// Формируем относительный путь: КодДокумента\ИмяФайла.Расширение
// Важно: НачатьПолучениеФайловССервера создаст папку автоматически
ИмяСРасширением = Выборка.Код + "\" + СсылкаНаФайл.Наименование + "." + СсылкаНаФайл.ТекущаяВерсияРасширение;
// Создаем описание передаваемого файла
ОписаниеФайла = Новый ОписаниеПередаваемогоФайла(ИмяСРасширением, АдресХранилища);
МассивРезультат.Добавить(ОписаниеФайла);
КонецЦикла;
КонецЦикла;
Возврат МассивРезультат;
КонецФункции
Теперь рассмотрим клиентскую процедуру, которая инициирует процесс сохранения. Важным моментом здесь является параметр КаталогВыгрузки. Метод НачатьПолучениеФайловССервера объединит базовый путь каталога с относительными путями, которые мы прописали в объектах ОписаниеПередаваемогоФайла на сервере.
&НаКлиенте
Процедура ВыгрузитьФайлы(Команда)
// Определяем базовый путь сохранения
ПутьДляСохранения = "D:\Export_1C_Files\";
// Получаем подготовленный массив описаний с сервера
СписокОбъектовДляВыгрузки = ПодготовитьМассивФайловДляВыгрузки();
Если СписокОбъектовДляВыгрузки.Количество() > 0 Тогда
// Запускаем асинхронное получение файлов
НачатьПолучениеФайловССервера(Неопределено, СписокОбъектовДляВыгрузки, ПутьДляСохранения);
ПоказатьОповещениеПользователя("Выгрузка завершена", , "Файлы сохранены в каталог " + ПутьДляСохранения);
Иначе
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Нет файлов для выгрузки.");
КонецЕсли;
КонецПроцедуры
При работе с реальными базами 1С:Документооборот, где количество файлов может исчисляться тысячами, а их размер — гигабайтами, необходимо учитывать несколько критических факторов, которые мы сейчас проанализируем.
1. Очистка имен файлов от недопустимых символов. Операционная система Windows запрещает использование символов / \ : * ? " < > | в названиях файлов. Поскольку в 1С пользователи часто называют документы произвольно, перед формированием пути обязательно нужно программно очищать строку. В противном случае метод НачатьПолучениеФайловССервера завершится с ошибкой доступа или не сможет создать файл.
2. Ограничение по памяти сервера. В приведенном выше коде все двоичные данные файлов помещаются во временное хранилище в рамках одного массива. Если вы попытаетесь выгрузить 1000 файлов по 10 Мб, серверу потребуется около 10 Гб оперативной памяти одновременно. Для массовых выгрузок мы рекомендуем выполнять процесс порциями (например, по 50 документов за раз) или упаковывать файлы в ZIP-архив прямо на сервере и передавать клиенту один единственный архивный файл.
3. Работа в веб-клиенте. Если ваши пользователи работают через браузер, механизм НачатьПолучениеФайловССервера может вести себя непредсказуемо из-за политик безопасности браузеров (блокировка множественного скачивания). В случае использования веб-клиента создание одного ZIP-архива является единственным стабильным решением.
4. Длина пути. Не забывайте про ограничение Windows в 255 символов на полный путь к файлу. Если у вас глубокая вложенность папок и длинные наименования документов, итоговый путь может превысить лимит, что приведет к ошибке Файл не найден при попытке записи.
Проанализируем ситуацию: стоит ли всегда писать свой код или лучше использовать типовые методы? В современных версиях «1С:Документооборот» (на базе БСП) существует модуль РаботаСФайламиКлиент, в котором есть метод СохранитьФайлы.
Этот метод хорош тем, что он автоматически обрабатывает:
Однако, если вам нужна жесткая структура папок типа Код\ИмяФайла, стандартный интерфейс может не подойти, и тогда ручное формирование ОписаниеПередаваемогоФайла, как мы разобрали выше, становится единственным выходом.
Мы рассмотрели эффективный способ программной выгрузки файлов из 1С:Документооборот. Основные преимущества данного подхода — это высокая скорость за счет пакетной передачи данных и возможность гибкого управления структурой папок на диске пользователя. При внедрении данного решения всегда помните о контроле оперативной памяти сервера и предварительной обработке имен файлов для исключения ошибок операционной системы.