Удаление файлов из кода 1С:Предприятия 8.3 на сервере и клиенте

· 11 мин

Содержание

Чтобы удалить файл в 1С программно, вызовите метод глобального контекста УдалитьФайлы("C:\Обмен\выгрузка.xml"). Перед этим проверьте через Новый Файл(Путь).Существует(), что файл есть, а сам вызов оберните в Попытка ... Исключение. На клиенте лучше вызывать асинхронный вариант УдалитьФайлыАсинх или НачатьУдалениеФайлов.

Сам метод занимает одну строку. Сложности начинаются в другом месте: код отработал без ошибок, а файл остался. Или удалилась вся папка вместо одного файла. Или на сервере выпало Ошибка при вызове метода контекста (УдалитьФайлы). У каждой из этих ситуаций есть конкретная причина и способ обойти. Всё описанное относится к платформе 1С:Предприятие 8.3 и не зависит от конфигурации.

Где выполняется код и чьи права работают при удалении файла

Первое, что нужно решить, — на каком компьютере лежит файл. Код 1С выполняется в двух местах, и у каждого своя файловая система.

Где кодДирективаЧья файловая системаПод чьими правами
Клиент (тонкий, толстый)&НаКлиентеКомпьютер пользователяУчётная запись Windows пользователя
Веб-клиент&НаКлиентеКомпьютер пользователя, только через расширениеУчётная запись пользователя
Сервер 1С (клиент-серверный вариант)&НаСервере, общие модули «Сервер»Сервер, где запущен рабочий процесс rphostУчётная запись службы агента сервера
Файловая база&НаСервереТот же компьютер пользователяУчётная запись пользователя

Отсюда три следствия:

  • 📁 Путь C:\Temp\отчет.xlsx в серверной процедуре — это диск C: сервера, а не рабочего места. Файл пользователя так не удалить.
  • 🔐 На сервере права определяет учётная запись службы 1С. По умолчанию установщик создаёт пользователя USR1CV8. Права пользователя 1С (роли) к файловой системе отношения не имеют.
  • 🧪 В файловой базе клиент и «сервер» — один процесс. Поэтому код, проверенный в файловом варианте, часто ломается после переезда на сервер.

Если файл создаёт сам код 1С и он нужен только на время операции, создавайте его на той же стороне, где потом удаляете. Тогда путаница с путями исключена.

Метод УдалитьФайлы и объект Файл: как удалить файл программно

Метод УдалитьФайлы(Путь, Маска) доступен и на клиенте, и на сервере. Работает он в двух режимах:

  1. Без маски. Путь указывает на файл или каталог. Если это каталог, он удаляется целиком, со всем содержимым.
  2. С маской. Путь трактуется как каталог, удаляются объекты, подходящие под маску, например "*.tmp".

Без маски вызов УдалитьФайлы(Каталог) сносит папку вместе с подпапками без подтверждения и без корзины. Ошибка в одной переменной, например пустое имя файла, превращает удаление файла в удаление каталога.

У объекта Файл метода удаления нет. Зато он даёт всё для проверок перед удалением:

Метод объекта ФайлЧто возвращает
Существует()Есть ли файл или каталог по пути
ЭтоФайл() / ЭтоКаталог()Что именно лежит по пути
ПолучитьТолькоЧтение()Установлен ли атрибут «только чтение»
УстановитьТолькоЧтение(Ложь)Снимает этот атрибут
ПолучитьВремяИзменения()Дату последнего изменения
Размер()Размер в байтах

Безопасная функция удаления одного файла

Функция ниже удаляет только файл. Каталог она не тронет, даже если в переменную попал путь к папке.

&НаСервере
Функция УдалитьФайлБезопасно(ПутьКФайлу) Экспорт

	Если Не ЗначениеЗаполнено(ПутьКФайлу) Тогда
		Возврат Ложь;
	КонецЕсли;

	Файл = Новый Файл(ПутьКФайлу);

	Если Не Файл.Существует() Тогда
		Возврат Истина; // удалять нечего, результат уже достигнут
	КонецЕсли;

	Если Не Файл.ЭтоФайл() Тогда
		ВызватьИсключение СтрШаблон("По пути %1 находится каталог, а не файл", ПутьКФайлу);
	КонецЕсли;

	Попытка
		Если Файл.ПолучитьТолькоЧтение() Тогда
			Файл.УстановитьТолькоЧтение(Ложь);
		КонецЕсли;
		УдалитьФайлы(Файл.ПолноеИмя);
	Исключение
		ЗаписьЖурналаРегистрации("Удаление файла",
			УровеньЖурналаРегистрации.Ошибка, , ,
			СтрШаблон("%1: %2", ПутьКФайлу, ОписаниеОшибки()));
		Возврат Ложь;
	КонецПопытки;

	Возврат Истина;

КонецФункции

Что здесь сделано осознанно:

  • ✅ Пустой путь отсекается сразу. Это главная защита от удаления не того.
  • ✅ Отсутствие файла считается успехом. Повторный запуск обработки не падает.
  • ✅ Атрибут «только чтение» снимается заранее: с ним удаление в Windows завершается ошибкой доступа.
  • ✅ Ошибка пишется в журнал регистрации с путём. Без пути запись в журнале бесполезна.

Удаление файлов на сервере 1С: пути, учётная запись, Linux

На сервере код работает в рабочем процессе кластера. Почти все проблемы серверного удаления сводятся к трём вещам.

Права учётной записи службы

Учётной записи, под которой запущена служба агента сервера 1С, нужно право на изменение каталога. Если папку создавал администратор вручную, у USR1CV8 там часто есть только чтение.

Как проверить:

  1. Откройте services.msc на сервере 1С и найдите службу агента сервера 1С:Предприятия 8.3.
  2. На вкладке «Вход в систему» посмотрите, под какой учётной записью она работает.
  3. В свойствах нужного каталога, вкладка «Безопасность», выдайте этой учётной записи право «Изменение».

Для сетевой папки этого мало: права нужны и на уровне общего ресурса, и на уровне NTFS. Локальная учётная запись USR1CV8 в сетевую папку другого компьютера обычно не попадает вовсе. Тут два пути: запустить службу под доменной учётной записью или держать рабочие файлы на локальном диске сервера.

Пути: только UNC, без сетевых дисков

Буква сетевого диска (Z:\Обмен) существует только в сеансе пользователя, который её подключил. Служба её не видит. На сервере пишите полный путь: \\fileserver\obmen\выгрузка.xml.

Сервер на Linux

  • 🐧 Разделитель — /, регистр букв в именах важен: Отчет.xlsx и отчет.xlsx — разные файлы.
  • 🐧 Служба работает под пользователем usr1cv8. Ему нужны права на запись в каталог, где лежит файл: в Linux удаление файла — это изменение каталога, а не самого файла.
  • 🐧 Чтобы код работал на любой ОС, собирайте пути через ПолучитьРазделительПути(), а не через жёсткий "\".
Разделитель = ПолучитьРазделительПути();
ПолныйПуть = КаталогОбмена + Разделитель + ИмяФайла;

Временные файлы на сервере

Если файл нужен на время операции, берите имя через ПолучитьИмяВременногоФайла("xml"). Платформа сама подберёт уникальное имя в каталоге временных файлов. Но удалять файл всё равно должен ваш код: после работы вызовите УдалитьФайлы для этого имени. Временные файлы, брошенные кодом, со временем занимают гигабайты на диске сервера.

Учтите балансировку: при нескольких рабочих процессах или серверах в кластере следующий серверный вызов может попасть в другой процесс, а то и на другой компьютер. Создавайте и удаляйте временный файл в рамках одного серверного вызова. Если файл нужно передать между вызовами — передавайте двоичные данные через ПоместитьВоВременноеХранилище, а не путь.

Удаление файла на стороне клиента: асинхронные методы и веб-клиент

На клиенте синхронный УдалитьФайлы работает не всегда. В свойствах конфигурации есть настройка «Режим использования синхронных вызовов расширений платформы и внешних компонент». В новых конфигурациях она стоит в значении «Не использовать». Тогда синхронный вызов на клиенте завершится ошибкой, и нужен асинхронный метод.

Вариант для платформы 8.3.18 и новее: Асинх и Ждать

&НаКлиенте
Асинх Процедура УдалитьВыгрузку(Команда)

	Путь = "C:\Обмен\выгрузка.xml";

	Попытка
		Ждать УдалитьФайлыАсинх(Путь);
		ПоказатьПредупреждение(, "Файл удалён");
	Исключение
		ПоказатьПредупреждение(, "Не удалось удалить файл: " + ОписаниеОшибки());
	КонецПопытки;

КонецПроцедуры

Вариант через описание оповещения

Подходит для более ранних релизов 8.3 и для конфигураций, где стиль с Асинх не принят.

&НаКлиенте
Процедура УдалитьВыгрузку(Команда)

	Путь = "C:\Обмен\выгрузка.xml";
	Оповещение = Новый ОписаниеОповещения("ПослеУдаленияФайла", ЭтотОбъект, Путь);
	НачатьУдалениеФайлов(Оповещение, Путь);

КонецПроцедуры

&НаКлиенте
Процедура ПослеУдаленияФайла(ДополнительныеПараметры) Экспорт

	Сообщить("Удалён файл " + ДополнительныеПараметры);

КонецПроцедуры

Веб-клиент

Браузер не пускает страницу в файловую систему. Чтобы веб-клиент удалил файл на компьютере пользователя, нужно расширение для работы с 1С:Предприятием. Порядок такой:

  1. Проверить, подключено ли оно: Ждать ПодключитьРасширениеРаботыСФайламиАсинх().
  2. Если вернулось Ложь — предложить установить: Ждать УстановитьРасширениеРаботыСФайламиАсинх().
  3. После подключения вызывать УдалитьФайлыАсинх как обычно.

Без расширения веб-клиент умеет только отдать файл пользователю на сохранение. Удалить что-то на его диске он не может. Если сценарий должен работать во всех клиентах, держите рабочие файлы на сервере.

Массовое удаление файлов и очистка каталогов

Типовые задачи: удалить все .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С — значит, права нужны учётной записи службы, как описано выше.

Перед запуском массовой очистки
Выполнено: 0 / 5

Обработка ошибок при удалении файлов

Любое удаление может упасть: файл открыт другой программой, нет прав, путь недоступен. Без Попытка ... Исключение одна такая ошибка прерывает всю обработку, и оставшиеся файлы не удаляются.

Чего не стоит делать:

  • ❌ Пустой блок Исключение КонецПопытки;. Ошибка исчезает бесследно, а файлы копятся на диске месяцами.
  • ❌ Сообщить() в серверном коде регламентного задания. Сообщение некому показать. Пишите в журнал регистрации.
  • ❌ Удаление сразу после записи файла другим процессом. Если внешняя программа ещё держит файл открытым, 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:\* превратит очистку в катастрофу.

Частые вопросы

Можно ли удалить файл в корзину, а не насовсем?
Встроенными методами — нет. УдалитьФайлы удаляет файл безвозвратно. Если нужна страховка, сначала переместите файл в архивную папку через ПереместитьФайл, а чистите архив по сроку.
Как удалить файл, присоединённый к документу в базе?
Присоединённые файлы в типовых конфигурациях хранятся в справочниках или томах на диске, и удалять их с диска напрямую нельзя: в базе останется ссылка на несуществующий файл. Помечайте на удаление сам элемент присоединённого файла штатными средствами конфигурации.
Чем УдалитьФайлы отличается от УдалитьИзВременногоХранилища?
УдалитьФайлы работает с файловой системой. УдалитьИзВременногоХранилища освобождает данные, которые код поместил во временное хранилище сеанса. Файлов на диске он не касается.
Почему в файловой базе удаление работает, а на сервере нет?
В файловой базе код выполняется под учётной записью пользователя Windows. На сервере — под учётной записью службы 1С, у которой обычно другие права и не подключены сетевые диски.
Как удалить сразу несколько конкретных файлов?
Соберите пути в массив и вызовите для каждого функцию безопасного удаления в цикле. Так ошибка на одном файле не остановит удаление остальных.