Как правильно сохранять файлы в 1С: решаем проблемы с именами, путями и клиент-серверным взаимодействием

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Разбор проблемы: почему файл не сохраняется с нужным именем

Проанализируем типичную ошибку. Разработчик пытается сформировать имя файла, используя строковое представление ссылки документа: ФайлНазвание = СокрЛП(ДокументОбъект.Ссылка) + ".xml". На первый взгляд, это логично, ведь ссылка содержит тип документа и его номер. Однако именно здесь кроется главная ловушка.

Рассмотрим ситуацию подробнее. Строковое представление ссылки (метод СокрЛП от объекта типа ДокументСсылка) обычно выглядит так: "Реализация товаров и услуг № 00001 от 01.01.2023 12:00:00". В операционных системах семейства Windows (и большинстве других) существует строгий список символов, которые запрещено использовать в именах файлов. К ним относятся:

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

Посмотрим на пример корректного формирования имени:


// Неправильно: содержит двоеточия
// ФайлНазвание = СокрЛП(ДокументОбъект.Ссылка) + ".xml"; 

// Правильно: используем номер документа
ИмяФайла = "Выгрузка_" + СокрЛП(ДокументОбъект.Номер) + ".xml";
ПутьКФайлу = КаталогВременныхФайлов() + ИмяФайла;

Использование Библиотеки стандартных подсистем (БСП) для очистки имен

Если в вашей конфигурации установлена БСП, мы рекомендуем не изобретать велосипед, а воспользоваться встроенными функциями очистки строк. Это гарантирует, что даже если в номере или наименовании документа окажутся кавычки или слэши, программа не "упадет" с ошибкой.

Разберем, как это сделать программно:


ИмяФайла = СтрШаблон("%1 №%2.xml", ДокументОбъект.Метаданные().Синоним, ДокументОбъект.Номер);
// Очищаем имя от запрещенных символов через БСП
ИмяФайла = СтроковыеФункцииКлиентСервер.ЗаменитьНедопустимыеСимволыИмениФайла(ИмяФайла, "_");
ПолныйПуть = КаталогВременныхФайлов() + ИмяФайла;

Функция ЗаменитьНедопустимыеСимволыИмениФайла автоматически заменит все "опасные" знаки на нижнее подчеркивание (или любой другой символ, который вы укажете во втором параметре).

Особенности клиент-серверного взаимодействия

Часто возникает ситуация: на локальной базе (файловой) код работает идеально, но при переносе на серверную базу файлы перестают сохраняться или "исчезают". Выясним причину: это происходит из-за разницы контекстов выполнения кода НаКлиенте и НаСервере.

Проанализируем ситуацию: когда вы вызываете КаталогВременныхФайлов() на стороне сервера, система возвращает путь в профиле пользователя, под которым запущена служба 1cv8 (например, usr1cv8). Этот путь физически находится на жестком диске сервера. Когда же код выполняется на стороне клиента, путь ведет в локальную папку Temp на компьютере пользователя.

Важные правила работы с путями на сервере:

  1. Доступ к дискам: Сервер 1С ничего не знает о ваших локальных дисках C: или D:. Попытка сохранить файл по пути C:\MyFiles\data.xml из серверного контекста приведет к тому, что 1С будет искать этот путь на сервере.
  2. Права доступа: Учетная запись, под которой работает служба сервера 1С, должна иметь полные права (чтение/запись) на целевую папку. Если папка сетевая, права должны быть даны именно пользователю домена, от имени которого работает сервер.
  3. Временное хранилище: Правильная схема работы предполагает создание файла на сервере, помещение его во временное хранилище и последующую передачу на клиент для сохранения через диалог.

Рассмотрим пример правильной передачи файла с сервера на клиент:


&НаСервере
Функция СформироватьФайлНаСервере()
    ИмяФайла = ПолучитьИмяВременногоФайла("xml");
    // ... здесь логика записи данных в файл ...
    ДвоичныеДанные = Новый ДвоичныеДанные(ИмяФайла);
    АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанные, ЭтаФорма.УникальныйИдентификатор);
    УдалитьФайлы(ИмяФайла);
    Возврат АдресХранилища;
КонецФункции

&НаКлиенте
Процедура СохранитьФайл()
    Адрес = СформироватьФайлНаСервере();
    ПараметрыДиалога = Новый ПараметрыДиалогаПолученияФайлов("Выберите путь для сохранения");
    ПолучитьФайлССервера(Адрес, "Выгрузка.xml", ПараметрыДиалога);
КонецПроцедуры

Управление диалогом выбора файла

Иногда требуется ограничить пользователя в выборе папки или скрыть лишние элементы интерфейса. Стандартный объект ДиалогВыбораФайла имеет свои ограничения. Рассмотрим их подробнее.

Вы можете задать начальный каталог с помощью свойства Каталог, но важно понимать: это не запретит пользователю перейти в другую папку через дерево каталогов. Если же ваша задача — полностью скрыть структуру папок и оставить только список файлов, стандартный диалог Windows/Linux этого сделать не позволит.

В таком случае мы рекомендуем реализовать собственную форму выбора. Для этого:

Посмотрим на пример использования НайтиФайлы для получения только XML-документов в конкретной папке:


СписокФайлов = НайтиФайлы("C:\ExchangeData\", "*.xml", Ложь);
Для Каждого ТекущийФайл Из СписокФайлов Цикл
    Если ТекущийФайл.ЭтоФайл() Тогда
        // Добавляем ТекущийФайл.Имя в таблицу на форме
    КонецЕсли;
КонецЦикла;

Параметр Ложь в методе НайтиФайлы означает, что поиск будет вестись только в указанном каталоге без захода в подпапки. Это и позволяет "отфильтровать" отображение каталогов для пользователя.

Кроссплатформенная разработка: разделители путей

Если ваша информационная база работает в смешанной среде (сервер на Linux, клиенты на Windows), вы обязательно столкнетесь с проблемой разделителей. В Windows используется обратный слэш \, а в Linux — прямой /.

Чтобы код был универсальным, проанализируем использование функции ПолучитьРазделительПути(). Никогда не пишите слэши вручную в строковых константах, если планируете кроссплатформенное использование.


Разделитель = ПолучитьРазделительПути();
ПолныйПуть = Каталог + Разделитель + ИмяФайла;

Также помните, что Linux чувствителен к регистру имен файлов. Файл Export.xml и export.xml для Linux — это два разных объекта, тогда как Windows будет считать их одним и тем же файлом. Всегда приводите программно формируемые имена к единому регистру, чтобы избежать ошибок "Файл не найден".

Безопасность и защита от опасных действий

В современных версиях платформы 8.3 (особенно начиная с 8.3.9) включена защита от опасных действий. При попытке программно записать файл на диск пользователя 1С может вывести предупреждение системы безопасности.

Чтобы избежать раздражающих окон для пользователя при работе с доверенными скриптами, эти действия можно настроить в профилях безопасности или отключить проверку для конкретной информационной базы в свойствах пользователя в конфигураторе. Однако лучшей практикой считается использование стандартных механизмов платформы для работы с файлами (ПоместитьФайл, ПолучитьФайл), которые проходят проверку безопасности более "мягко".

Подводя итог, скажем: стабильное сохранение файлов в 1С зависит от трех факторов: чистоты имени (отсутствие спецсимволов), понимания контекста (где выполняется код) и правильной обработки путей. Используя описанные выше методы, вы сможете избежать 99% типичных ошибок при работе с файловой системой.

← На главную