Удаление файлов из кода 1С:Предприятия 8.3 на сервере и клиенте
Содержание
Чтобы удалить файл в 1С программно, вызовите метод глобального контекста УдалитьФайлы("C:\Обмен\выгрузка.xml"). Перед этим проверьте через Новый Файл(Путь).Существует(), что файл есть, а сам вызов оберните в Попытка ... Исключение. На клиенте лучше вызывать асинхронный вариант УдалитьФайлыАсинх или НачатьУдалениеФайлов.
Сам метод занимает одну строку. Сложности начинаются в другом месте: код отработал без ошибок, а файл остался. Или удалилась вся папка вместо одного файла. Или на сервере выпало Ошибка при вызове метода контекста (УдалитьФайлы). У каждой из этих ситуаций есть конкретная причина и способ обойти. Всё описанное относится к платформе 1С:Предприятие 8.3 и не зависит от конфигурации.
Где выполняется код и чьи права работают при удалении файла
Первое, что нужно решить, — на каком компьютере лежит файл. Код 1С выполняется в двух местах, и у каждого своя файловая система.
| Где код | Директива | Чья файловая система | Под чьими правами |
|---|---|---|---|
| Клиент (тонкий, толстый) | &НаКлиенте | Компьютер пользователя | Учётная запись Windows пользователя |
| Веб-клиент | &НаКлиенте | Компьютер пользователя, только через расширение | Учётная запись пользователя |
| Сервер 1С (клиент-серверный вариант) | &НаСервере, общие модули «Сервер» | Сервер, где запущен рабочий процесс rphost | Учётная запись службы агента сервера |
| Файловая база | &НаСервере | Тот же компьютер пользователя | Учётная запись пользователя |
Отсюда три следствия:
- 📁 Путь
C:\Temp\отчет.xlsxв серверной процедуре — это диск C: сервера, а не рабочего места. Файл пользователя так не удалить. - 🔐 На сервере права определяет учётная запись службы 1С. По умолчанию установщик создаёт пользователя
USR1CV8. Права пользователя 1С (роли) к файловой системе отношения не имеют. - 🧪 В файловой базе клиент и «сервер» — один процесс. Поэтому код, проверенный в файловом варианте, часто ломается после переезда на сервер.
Если файл создаёт сам код 1С и он нужен только на время операции, создавайте его на той же стороне, где потом удаляете. Тогда путаница с путями исключена.
Метод УдалитьФайлы и объект Файл: как удалить файл программно
Метод УдалитьФайлы(Путь, Маска) доступен и на клиенте, и на сервере. Работает он в двух режимах:
- Без маски.
Путьуказывает на файл или каталог. Если это каталог, он удаляется целиком, со всем содержимым. - С маской.
Путьтрактуется как каталог, удаляются объекты, подходящие под маску, например"*.tmp".
Без маски вызов УдалитьФайлы(Каталог) сносит папку вместе с подпапками без подтверждения и без корзины. Ошибка в одной переменной, например пустое имя файла, превращает удаление файла в удаление каталога.
У объекта Файл метода удаления нет. Зато он даёт всё для проверок перед удалением:
| Метод объекта Файл | Что возвращает |
|---|---|
Существует() | Есть ли файл или каталог по пути |
ЭтоФайл() / ЭтоКаталог() | Что именно лежит по пути |
ПолучитьТолькоЧтение() | Установлен ли атрибут «только чтение» |
УстановитьТолькоЧтение(Ложь) | Снимает этот атрибут |
ПолучитьВремяИзменения() | Дату последнего изменения |
Размер() | Размер в байтах |
Безопасная функция удаления одного файла
Функция ниже удаляет только файл. Каталог она не тронет, даже если в переменную попал путь к папке.
&НаСервере
Функция УдалитьФайлБезопасно(ПутьКФайлу) Экспорт
Если Не ЗначениеЗаполнено(ПутьКФайлу) Тогда
Возврат Ложь;
КонецЕсли;
Файл = Новый Файл(ПутьКФайлу);
Если Не Файл.Существует() Тогда
Возврат Истина; // удалять нечего, результат уже достигнут
КонецЕсли;
Если Не Файл.ЭтоФайл() Тогда
ВызватьИсключение СтрШаблон("По пути %1 находится каталог, а не файл", ПутьКФайлу);
КонецЕсли;
Попытка
Если Файл.ПолучитьТолькоЧтение() Тогда
Файл.УстановитьТолькоЧтение(Ложь);
КонецЕсли;
УдалитьФайлы(Файл.ПолноеИмя);
Исключение
ЗаписьЖурналаРегистрации("Удаление файла",
УровеньЖурналаРегистрации.Ошибка, , ,
СтрШаблон("%1: %2", ПутьКФайлу, ОписаниеОшибки()));
Возврат Ложь;
КонецПопытки;
Возврат Истина;
КонецФункции
Что здесь сделано осознанно:
- ✅ Пустой путь отсекается сразу. Это главная защита от удаления не того.
- ✅ Отсутствие файла считается успехом. Повторный запуск обработки не падает.
- ✅ Атрибут «только чтение» снимается заранее: с ним удаление в Windows завершается ошибкой доступа.
- ✅ Ошибка пишется в журнал регистрации с путём. Без пути запись в журнале бесполезна.
Удаление файлов на сервере 1С: пути, учётная запись, Linux
На сервере код работает в рабочем процессе кластера. Почти все проблемы серверного удаления сводятся к трём вещам.
Права учётной записи службы
Учётной записи, под которой запущена служба агента сервера 1С, нужно право на изменение каталога. Если папку создавал администратор вручную, у USR1CV8 там часто есть только чтение.
Как проверить:
- Откройте
services.mscна сервере 1С и найдите службу агента сервера 1С:Предприятия 8.3. - На вкладке «Вход в систему» посмотрите, под какой учётной записью она работает.
- В свойствах нужного каталога, вкладка «Безопасность», выдайте этой учётной записи право «Изменение».
Для сетевой папки этого мало: права нужны и на уровне общего ресурса, и на уровне NTFS. Локальная учётная запись USR1CV8 в сетевую папку другого компьютера обычно не попадает вовсе. Тут два пути: запустить службу под доменной учётной записью или держать рабочие файлы на локальном диске сервера.
Пути: только UNC, без сетевых дисков
Буква сетевого диска (Z:\Обмен) существует только в сеансе пользователя, который её подключил. Служба её не видит. На сервере пишите полный путь: \\fileserver\obmen\выгрузка.xml.
Сервер на Linux
- 🐧 Разделитель —
/, регистр букв в именах важен:Отчет.xlsxиотчет.xlsx— разные файлы. - 🐧 Служба работает под пользователем
usr1cv8. Ему нужны права на запись в каталог, где лежит файл: в Linux удаление файла — это изменение каталога, а не самого файла. - 🐧 Чтобы код работал на любой ОС, собирайте пути через
ПолучитьРазделительПути(), а не через жёсткий"\".
Разделитель = ПолучитьРазделительПути();
ПолныйПуть = КаталогОбмена + Разделитель + ИмяФайла;
Временные файлы на сервере
Если файл нужен на время операции, берите имя через ПолучитьИмяВременногоФайла("xml"). Платформа сама подберёт уникальное имя в каталоге временных файлов. Но удалять файл всё равно должен ваш код: после работы вызовите УдалитьФайлы для этого имени. Временные файлы, брошенные кодом, со временем занимают гигабайты на диске сервера.
Учтите балансировку: при нескольких рабочих процессах или серверах в кластере следующий серверный вызов может попасть в другой процесс, а то и на другой компьютер. Создавайте и удаляйте временный файл в рамках одного серверного вызова. Если файл нужно передать между вызовами — передавайте двоичные данные через ПоместитьВоВременноеХранилище, а не путь.
Удаление файла на стороне клиента: асинхронные методы и веб-клиент
На клиенте синхронный УдалитьФайлы работает не всегда. В свойствах конфигурации есть настройка «Режим использования синхронных вызовов расширений платформы и внешних компонент». В новых конфигурациях она стоит в значении «Не использовать». Тогда синхронный вызов на клиенте завершится ошибкой, и нужен асинхронный метод.
Вариант для платформы 8.3.18 и новее: Асинх и Ждать
&НаКлиенте
Асинх Процедура УдалитьВыгрузку(Команда)
Путь = "C:\Обмен\выгрузка.xml";
Попытка
Ждать УдалитьФайлыАсинх(Путь);
ПоказатьПредупреждение(, "Файл удалён");
Исключение
ПоказатьПредупреждение(, "Не удалось удалить файл: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Вариант через описание оповещения
Подходит для более ранних релизов 8.3 и для конфигураций, где стиль с Асинх не принят.
&НаКлиенте
Процедура УдалитьВыгрузку(Команда)
Путь = "C:\Обмен\выгрузка.xml";
Оповещение = Новый ОписаниеОповещения("ПослеУдаленияФайла", ЭтотОбъект, Путь);
НачатьУдалениеФайлов(Оповещение, Путь);
КонецПроцедуры
&НаКлиенте
Процедура ПослеУдаленияФайла(ДополнительныеПараметры) Экспорт
Сообщить("Удалён файл " + ДополнительныеПараметры);
КонецПроцедуры
Веб-клиент
Браузер не пускает страницу в файловую систему. Чтобы веб-клиент удалил файл на компьютере пользователя, нужно расширение для работы с 1С:Предприятием. Порядок такой:
- Проверить, подключено ли оно:
Ждать ПодключитьРасширениеРаботыСФайламиАсинх(). - Если вернулось
Ложь— предложить установить:Ждать УстановитьРасширениеРаботыСФайламиАсинх(). - После подключения вызывать
УдалитьФайлыАсинхкак обычно.
Без расширения веб-клиент умеет только отдать файл пользователю на сохранение. Удалить что-то на его диске он не может. Если сценарий должен работать во всех клиентах, держите рабочие файлы на сервере.
Массовое удаление файлов и очистка каталогов
Типовые задачи: удалить все .tmp в папке обмена, очистить каталог
от выгрузок старше 30 дней, вычистить пустые подпапки.
Удаление по маске
УдалитьФайлы("\\fileserver\obmen\in", "*.tmp");
Коротко, но контроля нет: вы не знаете, что именно удалилось и что осталось. Маска может зацепить и вложенные каталоги. Для разовой чистки годится, для регламентной обработки лучше перебор.
Удаление файлов старше N дней
НайтиФайлы(Каталог, Маска, ИскатьВПодкаталогах) возвращает массив объектов Файл. По нему можно отобрать файлы по дате и удалить поштучно.
&НаСервере
Функция ОчиститьКаталог(Каталог, Маска = "*.*", ХранитьДней = 30) Экспорт
ГраницаУдаления = ТекущаяДата() - ХранитьДней * 86400; // время сервера
Удалено = 0;
НеУдалено = 0;
НайденныеФайлы = НайтиФайлы(Каталог, Маска, Истина);
Для Каждого Файл Из НайденныеФайлы Цикл
Если Не Файл.ЭтоФайл() Тогда
Продолжить;
КонецЕсли;
Если Файл.ПолучитьВремяИзменения() >= ГраницаУдаления Тогда
Продолжить;
КонецЕсли;
Попытка
УдалитьФайлы(Файл.ПолноеИмя);
Удалено = Удалено + 1;
Исключение
НеУдалено = НеУдалено + 1;
ЗаписьЖурналаРегистрации("Очистка каталога",
УровеньЖурналаРегистрации.Предупреждение, , ,
СтрШаблон("%1: %2", Файл.ПолноеИмя, ОписаниеОшибки()));
КонецПопытки;
КонецЦикла;
Возврат Новый Структура("Удалено, НеУдалено", Удалено, НеУдалено);
КонецФункции
Пересчёт границы: 30 дней × 86 400 секунд = 2 592 000 секунд. Вычитание числа из даты в 1С сдвигает дату на это количество секунд. Время изменения файла и ТекущаяДата() на сервере берутся с одних часов, поэтому сравнение корректно.
Удаление пустых подкаталогов
После чистки файлов остаются пустые папки. Удаляйте их отдельным проходом, проверяя, что внутри ничего нет:
Подкаталоги = НайтиФайлы(Каталог, "*", Ложь);
Для Каждого Подкаталог Из Подкаталоги Цикл
Если Подкаталог.ЭтоКаталог()
И НайтиФайлы(Подкаталог.ПолноеИмя, "*", Ложь).Количество() = 0 Тогда
УдалитьФайлы(Подкаталог.ПолноеИмя);
КонецЕсли;
КонецЦикла;
Здесь УдалитьФайлы без маски безопасен: каталог гарантированно пуст.
Запуск по расписанию
Функцию ОчиститьКаталог удобно вызывать из регламентного задания. В конфигураторе добавьте регламентное задание, укажите метод общего серверного модуля и расписание, например ежедневно в 03:00. В клиент-серверной базе задание выполнит сервер 1С — значит, права нужны учётной записи службы, как описано выше.
Обработка ошибок при удалении файлов
Любое удаление может упасть: файл открыт другой программой, нет прав, путь недоступен. Без Попытка ... Исключение одна такая ошибка прерывает всю обработку, и оставшиеся файлы не удаляются.
Чего не стоит делать:
- ❌ Пустой блок
Исключение КонецПопытки;. Ошибка исчезает бесследно, а файлы копятся на диске месяцами. - ❌
Сообщить()в серверном коде регламентного задания. Сообщение некому показать. Пишите в журнал регистрации. - ❌ Удаление сразу после записи файла другим процессом. Если внешняя программа ещё держит файл открытым, Windows не даст его удалить. Пусть такой файл удалится при следующем запуске очистки.
Безопасный режим и профили безопасности
Внешние обработки, расширения в безопасном режиме и код после УстановитьБезопасныйРежим(Истина) не имеют доступа к файловой системе. Если в кластере включены профили безопасности, каталог, с которым работает код, должен быть разрешён в профиле. В типовых конфигурациях на БСП внешняя обработка запрашивает такие разрешения при регистрации, а администратор подтверждает их. Отключать профили ради одной обработки не нужно: правильнее добавить разрешение на конкретный каталог.
Другие способы удалить файл: БСП, FileSystemObject, командная строка
Встроенных методов хватает почти всегда. Альтернативы нужны в редких случаях.
| Способ | Когда применять | Ограничения |
|---|---|---|
УдалитьФайлы | Обычное удаление на сервере и клиенте | Каталог без маски удаляется целиком |
УдалитьФайлыАсинх / НачатьУдалениеФайлов | Клиент, веб-клиент, запрет синхронных вызовов | Только клиентский код |
Модуль ФайловаяСистема из БСП | Временные файлы и каталоги в типовых конфигурациях | Только в конфигурациях на БСП 3.x |
COM-объект Scripting.FileSystemObject | Нужно удалить файл с атрибутом «только чтение» одной командой | Только Windows, требует разрешения COM в безопасном режиме |
ЗапуститьПриложение с командой ОС | Сложная очистка, которую проще сделать скриптом | Нет контроля ошибок по каждому файлу, зависимость от ОС |
Модуль ФайловаяСистема (БСП)
В типовых конфигурациях на БСП 3.x есть общий модуль ФайловаяСистема с процедурами УдалитьВременныйФайл и УдалитьВременныйКаталог. Их удобно использовать в паре с СоздатьВременныйКаталог из того же модуля: удаление уже обёрнуто в обработку ошибок и запись в журнал.
ВременныйКаталог = ФайловаяСистема.СоздатьВременныйКаталог();
// ... работа с файлами в каталоге
ФайловаяСистема.УдалитьВременныйКаталог(ВременныйКаталог);
FileSystemObject через COM
FSO = Новый COMОбъект("Scripting.FileSystemObject");
FSO.DeleteFile("C:\Обмен\выгрузка.xml", Истина); // Истина — удалить и при «только чтение»
Способ работает только на Windows. На сервере под Linux такой код упадёт при создании объекта.
Команда операционной системы
ЗапуститьПриложение("cmd /c del /q ""C:\Обмен\*.tmp""", , Истина);
Третий параметр Истина заставляет 1С дождаться завершения команды. Минус в том, что 1С не узнает, какие файлы не удалились и почему. Используйте этот путь только там, где встроенные методы не справляются.
Никогда не собирайте строку команды из данных, которые ввёл пользователь или прислала внешняя система. Имя файла вида a.txt" & del /s /q C:\* превратит очистку в катастрофу.