К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как программно скопировать файл в 1С

Как в 1С программно скопировать файл: метод КопироватьФайл(), работа на клиенте и сервере, проверка результата, типовые ошибки и готовые примеры кода.

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

Главная сложность не в самом методе, а в контексте исполнения: файловая система клиента и файловая система сервера — это разные среды. Код, который отлично работает в файловом режиме на компьютере разработчика, в клиент-серверном варианте может «не видеть» ни исходный файл, ни папку назначения. Поэтому перед написанием кода важно определить, где физически лежит файл и где выполняется код.

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

Синтаксис метода КопироватьФайл

Метод имеет два обязательных параметра: полное имя файла-источника и полное имя файла-приёмника. Оба параметра — строки с абсолютными путями. Относительные пути платформа не разворачивает от «текущего каталога» в привычном смысле, поэтому всегда формируйте полный путь явно.

КопироватьФайл("C:\Данные\отчет.xlsx", "D:\Архив\отчет_копия.xlsx");

Если файл-приёмник уже существует, он будет перезаписан без предупреждения. Если каталог приёмника не существует, платформа вызовет исключение — каталог нужно создать заранее методом СоздатьКаталог(). Сам метод ничего не возвращает: успешное выполнение означает, что файл скопирован, а любая ошибка (нет файла, нет прав, путь недоступен) приводит к исключению, которое следует обрабатывать через Попытка...Исключение.

Копирование на клиенте

Когда код выполняется на клиенте (директива &НаКлиенте), метод работает с диском компьютера пользователя. Это подходит для сценариев вроде «сохранить копию выгрузки в папку, которую выбрал пользователь» или «скопировать шаблон из сетевой папки на локальный диск».

&НаКлиенте

Процедура СкопироватьНаКлиенте(Команда)

Источник = "C:\Выгрузки\заказы.xml";

Приемник = "D:\Архив\заказы_копия.xml";

Попытка

КопироватьФайл(Источник, Приемник);

Сообщить("Файл скопирован: " + Приемник);

Исключение

Сообщить("Ошибка копирования: " + ОписаниеОшибки());

КонецПопытки;

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

В тонком и веб-клиенте доступ к файловой системе ограничен: для работы с файлами вне диалога выбора требуется расширение работы с файлами. Если оно не установлено, синхронный вызов КопироватьФайл() завершится ошибкой. В современных версиях платформы рекомендуется асинхронный вариант — НачатьКопированиеФайла() с описанием оповещения, который корректно запрашивает расширение у пользователя.

Копирование на сервере

Серверный контекст (&НаСервере) работает с файловой системой сервера 1С, а не компьютера пользователя. Это принципиально: путь C:\... на сервере указывает на диск сервера, и файл, который пользователь видит у себя, оттуда недоступен.

Копирование на сервере применяют для регламентных операций: архивация выгрузок в сетевой каталог, подготовка файлов для обмена, резервные копии. Учётная запись, под которой работает служба агента сервера 1С (обычно USR1CV8), должна иметь права на чтение источника и запись в каталог назначения — это самая частая причина ошибок «вне регламентов».

&НаСервере

Процедура СкопироватьНаСервере()

Источник = "\\fileserver\obmen\price.xml";

КаталогАрхива = "\\fileserver\obmen\archive\";

Если НЕ ФайлСуществует(КаталогАрхива) Тогда

СоздатьКаталог(КаталогАрхива);

КонецЕсли;

Приемник = КаталогАрхива + "price_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".xml";

КопироватьФайл(Источник, Приемник);

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

Передача файла между клиентом и сервером

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

&НаСервере

Процедура СохранитьФайлНаСервере(АдресХранилища, ИмяФайла)

ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);

ПутьНаСервере = "\\fileserver\obmen\inbox\" + ИмяФайла;

ДвоичныеДанные.Записать(ПутьНаСервере);

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

Обратная задача — отдать файл с сервера клиенту — решается зеркально: на сервере данные читаются (Новый ДвоичныеДанные(Путь)), помещаются в хранилище через ПоместитьВоВременноеХранилище, а клиент получает их и записывает локально. После использования хранилище очищают методом УдалитьИзВременногоХранилища, чтобы не копить данные в памяти сеанса.

Порядок действий
  1. 1
    Определите, где лежит файл и где должен оказаться: клиент, сервер или передача между ними
  2. 2
    Сформируйте полные пути к источнику и приёмнику
  3. 3
    Убедитесь, что каталог назначения существует, при необходимости создайте его методом СоздатьКаталог
  4. 4
    Вызовите КопироватьФайл внутри конструкции Попытка...Исключение
  5. 5
    Проверьте результат: существование файла-приёмника и его размер
  6. 6
    При передаче между клиентом и сервером используйте временное хранилище вместо прямого копирования

Проверка результата и обработка ошибок

Доверять молчаливому выполнению нельзя: файл может отсутствовать, быть заблокированным другим процессом (например, открыт в Excel), а путь — содержать опечатку. Минимальный набор проверок: существование источника до копирования и существование приёмника после.

Для проверки существования файла удобен объект Файл:

Ф = Новый Файл(Источник);

Если НЕ Ф.Существует() Тогда

ВызватьИсключение "Файл-источник не найден: " + Источник;

КонецЕсли;

Дополнительно полезно сравнить размеры источника и копии — расхождение означает, что копирование было прервано (обрыв сети при работе с сетевым каталогом, нехватка места). Все операции оборачивайте в Попытка...Исключение и логируйте ОписаниеОшибки() в журнал регистрации или в сообщение пользователю — иначе диагностика проблем в рабочей базе превратится в гадание.

Контрольные точки

Как проверить результат

Существование файла-приёмника
Норма

Объект Файл по пути приёмника, метод Существует() возвращает Истина

Тревожный признак

Файл отсутствует — копирование не выполнено или путь неверен

Размер копии
Норма

Размер совпадает с размером источника

Тревожный признак

Размер меньше или равен нулю — копирование прервано

Доступность файла
Норма

Файл открывается и читается

Тревожный признак

Ошибка доступа — файл заблокирован другим процессом или нет прав

Типичные ошибки и ограничения

Первая и самая массовая ошибка — путаница контекстов: разработчик тестирует код в файловой базе, где клиент и сервер фактически на одной машине, а в клиент-серверном режиме сервер не видит локальные диски пользователей. Вторая — отсутствие прав у учётной записи агента сервера на сетевой каталог: локальный администратор сервера по умолчанию не имеет доступа к сетевым ресурсам, права нужно выдавать явно.

Третья группа проблем — блокировки и спецсимволы. Файл, открытый в другой программе с эксклюзивным доступом, скопировать не удастся. Сетевые пути записывайте в формате UNC (\\сервер\ресурс\...), а не через подключённые сетевые диски — буквы дисков у службы сервера 1С обычно не подключены. В Linux-версии сервера пути чувствительны к регистру и используют прямые слэши, что ломает код, написанный под Windows.

Типичные ошибки
01
Вызов КопироватьФайл на сервере с путём к локальному диску пользователя — в клиент-серверном режиме файл не найден
02
Отсутствие Попытка...Исключение — любая ошибка доступа прерывает обработку целиком
03
Использование сетевого диска (Z:\) вместо UNC-пути — у службы сервера 1С такой диск не подключён
04
Несозданный каталог назначения — метод не создаёт каталоги автоматически и вызывает исключение
05
Копирование файла, открытого другим приложением с блокировкой — ошибка доступа

Альтернативные способы и выбор подхода

Кроме КопироватьФайл(), файл можно перенести через чтение и запись содержимого: Новый ДвоичныеДанные(Источник) с последующим Записать(Приемник). Этот способ нужен, когда файл требуется не просто скопировать, а передать через хранилище, отправить по HTTP или поместить в реквизит базы. Для перемещения без оставления оригинала есть метод ПереместитьФайл(), для массовых операций — НайтиФайлы() с копированием в цикле.

Сравнение вариантов

КопироватьФайл

Быстрое копирование в пределах одной файловой системы. Не подходит для передачи между клиентом и сервером

ДвоичныеДанные + Записать

Универсально: работает с хранилищем, HTTP, реквизитами. Требует больше кода и памяти под содержимое файла

ПереместитьФайл

Когда оригинал сохранять не нужно. Риск: при ошибке на середине файл можно потерять

НачатьКопированиеФайла

Асинхронный вариант для тонкого и веб-клиента с расширением работы с файлами

Выбор простой: в пределах одной стороны — КопироватьФайл(), между клиентом и сервером — временное хранилище с двоичными данными, массовая обработка — НайтиФайлы() плюс копирование в цикле с обработкой ошибок на каждой итерации, чтобы один «битый» файл не остановил всю пачку.

Итог

Что важно запомнить

КопироватьФайл(Источник, Приемник) работает там, где исполняется код. Всегда используйте полные пути, создавайте каталог назначения заранее, оборачивайте вызов в Попытка...Исключение и проверяйте результат. Для обмена между клиентом и сервером применяйте временное хранилище.

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

Почему КопироватьФайл работает в файловой базе, но не в клиент-серверной?

В файловом режиме клиент и «сервер» выполняются на одном компьютере, поэтому любые пути доступны. В клиент-серверном режиме серверный код видит только диски сервера. Решение — передавать файл через временное хранилище или класть файлы в общий сетевой каталог, доступный обеим сторонам.

Можно ли скопировать файл, если он открыт в другой программе?

Зависит от режима открытия. Если программа открыла файл с блокировкой записи (типично для Excel), копирование завершится ошибкой доступа. Надёжный вариант — обернуть вызов в Попытка...Исключение и повторить попытку позже или скопировать через чтение двоичных данных, если чтение не заблокировано.

Перезаписывает ли КопироватьФайл существующий файл?

Да, файл-приёмник перезаписывается без предупреждения. Если нужно сохранять версии, формируйте уникальное имя, например добавляя к нему дату и время, или проверяйте существование файла перед копированием.

Как скопировать все файлы из папки?

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

Работает ли метод в веб-клиенте?

Синхронный КопироватьФайл требует расширения работы с файлами и подтверждения пользователя. Рекомендуемый подход — асинхронный НачатьКопированиеФайла с оповещением о завершении, либо передача файла на сервер через временное хранилище и копирование уже там.

Как скопировать файл на сетевой диск с сервера 1С?

Используйте UNC-путь вида \\сервер\ресурс\папка вместо буквы сетевого диска — у службы агента сервера подключённые диски отсутствуют. Учётной записи службы должны быть выданы права на запись в этот сетевой ресурс.