Перемещение файлов во встроенном языке 1С: ПереместитьФайл, COM и сетевые папки
Содержание
Чтобы переместить файл в 1С программно, вызовите метод глобального контекста ПереместитьФайл(ИмяФайлаИсточника, ИмяФайлаПриемника). Он переносит файл и при необходимости меняет его имя за одну операцию. На клиенте с асинхронным режимом используйте ПереместитьФайлАсинх (платформа 8.3.18 и выше) или НачатьПеремещениеФайла на более ранних версиях.
Сам вызов — одна строка. Проблемы начинаются вокруг него: нет каталога-приёмника, файл с таким именем уже лежит, сетевая папка не видна службе сервера, код выполняется не на том компьютере. Каждый из этих случаев решается парой строк кода, если знать, где искать.
Метод ПереместитьФайл: синтаксис и базовый пример
Метод принимает два полных пути: откуда и куда. В пути приёмника указывается имя файла, а не только каталог. Если имя другое, файл переедет и сразу переименуется.
Источник = "C:\Обмен\Входящие\order_001.xml";
Приемник = "C:\Обмен\Архив\order_001.xml";
ПереместитьФайл(Источник, Приемник);
Что важно знать о методе:
- 📍 Где работает. Сервер, толстый клиент, тонкий клиент, внешнее соединение. В веб-клиенте — только с расширением работы с файлами и с учётом режима синхронных вызовов.
- 📍 На каком компьютере. Пути считаются на той машине, где выполняется код.
&НаСервере— это диск сервера 1С,&НаКлиенте— диск пользователя. - 📍 Каталоги. Методом можно переносить и папку целиком, но на практике надёжнее работать с файлами по одному: так проще ловить ошибки.
- 📍 Ошибки. Метод ничего не возвращает. Неудача — это исключение, поэтому вызов всегда оборачивают в
Попытка … Исключение.
Для переименования файла отдельного метода нет. Переименование — это тот же ПереместитьФайл в пределах одного каталога: ПереместитьФайл(Каталог + "old.txt", Каталог + "new.txt").
Разделитель пути
Не склеивайте пути через жёсткий "\", если код может попасть на сервер под Linux. Платформа отдаёт правильный разделитель сама:
Разделитель = ПолучитьРазделительПути();
Приемник = КаталогАрхива + Разделитель + ИмяФайла;
В конфигурациях на БСП для этого же есть ОбщегоНазначенияКлиентСервер.ДобавитьКонечныйРазделительПути(Путь) — он добавит слеш, только если его нет.
Подготовка к перемещению: проверки, каталог, имя
Голый ПереместитьФайл в рабочем коде почти не встречается. Перед ним стоят три проверки. Они снимают большую часть падений обработки.
- Источник существует и это файл. Объект
ФайлдаётСуществует()иЭтоФайл(). - Каталог-приёмник есть. Если нет — создаём его через
СоздатьКаталог(). Метод создаёт всю цепочку вложенных папок. - Имя в приёмнике свободно. Не полагайтесь на то, как платформа поведёт себя при занятом имени. Решите это явно: удалить старый файл, пропустить или выбрать новое имя.
Функция, которую можно класть в общий модуль:
// Возвращает полный путь к перемещённому файлу или пустую строку при ошибке.
Функция ПереместитьФайлБезопасно(ПутьИсточника, КаталогПриемника, Заменять = Ложь) Экспорт
ФайлИсточник = Новый Файл(ПутьИсточника);
Если Не ФайлИсточник.Существует() Или Не ФайлИсточник.ЭтоФайл() Тогда
Возврат "";
КонецЕсли;
КаталогОбъект = Новый Файл(КаталогПриемника);
Если Не КаталогОбъект.Существует() Тогда
СоздатьКаталог(КаталогПриемника);
КонецЕсли;
ПутьПриемника = КаталогПриемника + ПолучитьРазделительПути() + ФайлИсточник.Имя;
ФайлПриемник = Новый Файл(ПутьПриемника);
Если ФайлПриемник.Существует() Тогда
Если Заменять Тогда
УдалитьФайлы(ПутьПриемника);
Иначе
ПутьПриемника = КаталогПриемника + ПолучитьРазделительПути()
+ ФайлИсточник.ИмяБезРасширения + "_"
+ Формат(ТекущаяДатаСеанса(), "ДФ=yyyyMMdd_HHmmss")
+ ФайлИсточник.Расширение;
КонецЕсли;
КонецЕсли;
Попытка
ПереместитьФайл(ПутьИсточника, ПутьПриемника);
Исключение
ЗаписьЖурналаРегистрации("Перемещение файлов", УровеньЖурналаРегистрации.Ошибка,,,
"Не удалось переместить " + ПутьИсточника + ": " + ОписаниеОшибки());
Возврат "";
КонецПопытки;
Возврат ПутьПриемника;
КонецФункции
Свойство Расширение объекта Файл возвращает расширение вместе с точкой (.xml), поэтому точку при склейке добавлять не нужно.
Метка времени с точностью до секунды не спасает, если за секунду приходит несколько файлов с одинаковым именем. Для потоков обмена добавляйте к имени счётчик или Новый УникальныйИдентификатор().
Атомарная передача файла другой программе
Частая задача: 1С выгружает файл в папку, а другая система (сканер папки, банк-клиент, служба обмена) его подхватывает. Если писать сразу под итоговым именем, внешняя программа может схватить недописанный файл.
Приём практика:
- Записать файл в ту же папку под временным именем, например
order_001.xml.tmp. - Дописать и закрыть его полностью.
- Переименовать через
ПереместитьФайлвorder_001.xml.
Переименование внутри одного тома происходит мгновенно. Внешняя программа видит файл уже целым.
Перемещение файлов по маске и пакетом
Для разбора каталога обмена нужен перенос сразу многих файлов. Список собирает НайтиФайлы(Каталог, Маска, ИскатьВПодкаталогах), а дальше — цикл:
Найденные = НайтиФайлы("D:\Обмен\Входящие", "*.xml", Ложь);
Перемещено = 0;
Для Каждого ФайлОбмена Из Найденные Цикл
Если Не ФайлОбмена.ЭтоФайл() Тогда
Продолжить;
КонецЕсли;
Результат = ПереместитьФайлБезопасно(ФайлОбмена.ПолноеИмя, "D:\Обмен\Обработанные");
Если ЗначениеЗаполнено(Результат) Тогда
Перемещено = Перемещено + 1;
КонецЕсли;
КонецЦикла;
Сообщить(СтрШаблон("Перемещено файлов: %1 из %2",
Формат(Перемещено, "ЧН=0; ЧГ=0"), Формат(Найденные.Количество(), "ЧН=0; ЧГ=0")));
Пара замечаний из практики:
- 🔹
НайтиФайлывозвращает массив объектовФайл, а не строк. Путь берите изПолноеИмя. - 🔹 Перемещайте файл после успешной загрузки его содержимого в базу, а не до. Иначе при ошибке загрузки файл уже окажется в архиве, и его никто не обработает.
- 🔹 Для файлов с ошибкой заведите отдельную папку
Ошибки. Так входящий каталог не забивается «вечными» файлами, которые падают при каждом запуске регламентного задания. - 🔹 Маска поддерживает
*и?. Для нескольких расширений вызовитеНайтиФайлынесколько раз.
Перемещение через COM-объект FileSystemObject
На Windows есть альтернатива — стандартный компонент Scripting.FileSystemObject. Его создают через COMОбъект на сервере или на Windows-клиенте:
FSO = Новый COMОбъект("Scripting.FileSystemObject");
Если FSO.FileExists("C:\Обмен\out.xml") Тогда
FSO.MoveFile("C:\Обмен\out.xml", "\\fileserver\exchange\out.xml");
КонецЕсли;
Особенности MoveFile:
- 🧩 Если приёмник уже существует, метод выдаёт ошибку. Замены «поверх» нет — сначала
DeleteFile. - 🧩 Путь приёмника, оканчивающийся на
\, трактуется как папка: файл переедет в неё под своим именем. - 🧩 Источник может содержать маску:
FSO.MoveFile("C:\Обмен\*.xml", "D:\Архив\")перенесёт все XML одной строкой. - 🧩 Для копирования с перезаписью есть
CopyFile(Источник, Приемник, Истина), для папок —MoveFolder.
Когда какой способ брать:
| Способ | Когда подходит | Ограничения |
|---|---|---|
ПереместитьФайл | Почти всегда, основной вариант | Нет масок, занятое имя проверяйте сами |
ПереместитьФайлАсинх / НачатьПеремещениеФайла | Клиентский код, веб-клиент | Нужен асинхронный стиль кода |
FileSystemObject.MoveFile | Пакетный перенос по маске на Windows | Только Windows, не работает на Linux-сервере и в веб-клиенте |
| Копирование + удаление | Перенос между томами и по сети, когда важна проверка | Две операции, нужен контроль результата |
COM-вариант привязывает код к Windows. Если сервер 1С когда-нибудь переедет на Linux, все вызовы COMОбъект придётся переписывать. Без веской причины берите встроенные методы.
Как переместить файл в сетевую папку: пути и права
Сетевые пути — главный источник ошибок «на сервере не работает , а у меня работает».
UNC вместо буквы диска
Пишите путь в формате \\fileserver\exchange\in\file.xml. Подключённые буквы дисков (Z:\) существуют только в сеансе конкретного пользователя Windows. Служба сервера 1С их не видит, даже если на сервере под администратором диск подключён.
Чьими правами работает код
| Где выполняется код | Чьими правами идёт доступ к файлам |
|---|---|
&НаСервере, клиент-серверная база | Учётная запись службы агента сервера 1С (по умолчанию USR1CV8) |
&НаСервере, файловая база | Пользователь Windows, запустивший 1С |
&НаКлиенте, тонкий или толстый клиент | Пользователь Windows на компьютере клиента |
| Регламентное задание | Учётная запись службы сервера 1С |
Отсюда рабочий порядок для клиент-серверной базы:
- Узнать, под какой учётной записью запущена служба агента сервера 1С (оснастка «Службы» Windows, вкладка «Вход в систему»).
- Если это локальная учётная запись — перевести службу на доменную, иначе файловый сервер её не узнает.
- Выдать этой записи права на общую папку и на файловую систему: чтение и удаление в источнике, запись в приёмнике.
- Перезапустить службу в нерабочее время.
Перезапуск службы агента сервера 1С обрывает все сеансы пользователей и прерывает регламентные задания. Делайте его вечером или в согласованное окно и предупредите пользователей заранее.
Сервер на Linux
На Linux сетевую папку сначала монтируют в файловую систему (например, через cifs в /mnt/exchange), а в коде пишут уже локальный путь /mnt/exchange/in/file.xml. Права проверяют для пользователя, от которого работает сервер 1С (обычно usr1cv8).
Перенос между томами и по сети
Когда источник и приёмник на разных дисках или на разных машинах, перемещение по сути превращается в копирование с удалением. При обрыве сети на середине можно получить обрезанный файл в приёмнике. Надёжнее сделать это руками и сверить размер:
КопироватьФайл(Источник, Приемник);
Если (Новый Файл(Приемник)).Размер() = (Новый Файл(Источник)).Размер() Тогда
УдалитьФайлы(Источник);
Иначе
ВызватьИсключение "Размер копии не совпал с исходным файлом: " + Источник;
КонецЕсли;
Перемещение файлов на клиенте, в веб-клиенте и на сервере
Директива компиляции определяет, чей диск вы трогаете. Это ключ к большинству вопросов «файл не находится».
Сервер
Код &НаСервере или в общем модуле с флагом «Сервер» видит только диски сервера 1С. Пользовательский рабочий стол оттуда недоступен. Обычный синхронный ПереместитьФайл здесь — правильный выбор.
Тонкий клиент и асинхронные методы
В конфигурациях, где запрещены синхронные вызовы (свойство конфигурации «Режим использования синхронных вызовов расширений платформы и внешних компонент»), на клиенте используйте асинхронный вариант:
&НаКлиенте
Асинх Процедура ПереместитьВыгрузку(Команда)
Попытка
Ждать ПереместитьФайлАсинх(ПутьИсточника, ПутьПриемника);
ПоказатьПредупреждение(, "Файл перемещён");
Исключение
ПоказатьПредупреждение(, "Не удалось переместить файл: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Конструкция Асинх/Ждать доступна с платформы 8.3.18. На платформах с номером ниже 8.3.18 используйте НачатьПеремещениеФайла с ОписаниеОповещения; порядок параметров процедуры-обработчика сверьте в синтакс-помощнике своей платформы.
Веб-клиент
Браузер сам по себе не даёт доступа к дискам пользователя. Перед любой работой с локальными файлами нужно подключить расширение работы с файлами:
&НаКлиенте
Асинх Процедура ПереместитьВВебКлиенте(Команда)
Подключено = Ждать ПодключитьРасширениеРаботыСФайламиАсинх();
Если Не Подключено Тогда
НачатьУстановкуРасширенияРаботыСФайлами();
Возврат;
КонецЕсли;
Ждать ПереместитьФайлАсинх(ПутьИсточника, ПутьПриемника);
КонецПроцедуры
При первом запуске пользователь увидит предложение установить расширение . Без него код упадёт.
Файл нужно перенести с клиента на сервер
ПереместитьФайл не умеет «переносить между компьютерами». Схема такая: на клиенте прочитать файл в ДвоичныеДанные и положить во временное хранилище, на сервере достать их и записать на диск, затем удалить исходный файл на клиенте.
&НаКлиенте
Процедура ОтправитьНаСервер(Команда)
Данные = Новый ДвоичныеДанные(ПутьНаКлиенте);
Адрес = ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор);
Если ЗаписатьНаСервере(Адрес, "order_001.xml") Тогда
УдалитьФайлы(ПутьНаКлиенте);
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция ЗаписатьНаСервере(Адрес, ИмяФайла)
Данные = ПолучитьИзВременногоХранилища(Адрес);
Данные.Записать("D:\Обмен\Входящие\" + ИмяФайла);
УдалитьИзВременногоХранилища(Адрес);
Возврат Истина;
КонецФункции
Исходный файл удаляется только после того, как сервер подтвердил запись. Если запись упадёт, исключение прервёт процедуру раньше УдалитьФайлы, и файл у пользователя останется.
Безопасный режим
Внешние обработки и расширения конфигурации
, подключённые в безопасном режиме, к файловой системе не допускаются. Тогда ПереместитьФайл выдаст ошибку о недостатке прав, хотя путь верный. Решение — запуск без безопасного режима или профиль безопасности с разрешением на нужный каталог; это настраивает администратор базы.
Обработка ошибок при перемещении файла
Перемещение падает исключением, а не возвращает Ложь. Отсюда правило: каждый вызов в Попытка, текст ошибки — в журнал регистрации, а не только пользователю. Регламентное задание сообщения на экран не покажет.
Типовой обработчик:
Попытка
ПереместитьФайл(Источник, Приемник);
Исключение
ТекстОшибки = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Обмен.ПеремещениеФайла",
УровеньЖурналаРегистрации.Ошибка, , ,
СтрШаблон("%1 -> %2: %3", Источник, Приемник, ТекстОшибки));
// решаем: пропустить файл, отправить в папку Ошибки или прервать весь обмен
КонецПопытки;
Что обычно стоит за ошибкой:
Повтор при занятом файле
Если файл кладёт внешняя программа, он может быть ещё открыт на запись в момент обработки. Не крутите повтор в цикле без паузы на сервере. Правильнее оставить файл на месте и забрать его при следующем запуске регламентного задания — через минуту он уже будет закрыт.
Как ускорить и упростить работу с файлами
Несколько правил, которые снимают проблемы до их появления:
- ✅ Один каталог — одна роль.
Входящие,Обработанные,Ошибки. Код не должен перебирать архив при каждом запуске. - ✅ Не держите в папке десятки тысяч файлов.
НайтиФайлыпо такому каталогу работает заметно дольше. Раскладывайте архив по подпапкам с датой:Архив\2026-10\. - ✅ Закрывайте потоки. После
ЧтениеXML,ЧтениеТекста,ЗаписьТекставызывайтеЗакрыть()до перемещения. Иначе файл остаётся занятым процессом 1С. - ✅ Временные файлы — через платформу.
ПолучитьИмяВременногоФайла("xml")даёт уникальное имя в каталоге временных файлов. В типовых на БСП есть общий модульФайловаяСистемас обёртками для временных файлов и каталогов — загляните в него, прежде чем писать свои. - ✅ Пути — в настройки. Каталоги обмена храните в константах или регистре сведений, а не строками в коде. При переезде сервера правится одна запись.
- ✅ Логируйте успех тоже. Одна строка в журнале регистрации на каждый перенесённый файл потом экономит время на разборе «куда делась выгрузка».