Как получить размер файла в 1С на сервере и почему возникает ошибка «Файл не существует»?

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

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

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

Почему сетевые пути возвращают «Ложь» на сервере?

Когда вы запускаете обработку на клиенте, код выполняется в контексте вашей учетной записи Windows. У вас могут быть подключены сетевые диски (например, диск K:\), и операционная система прозрачно авторизует ваши запросы к сетевым хранилищам. Но как только этот же код переносится на сервер приложений 1С (в серверный модуль или фоновое задание), контекст выполнения кардинально меняется.

Проанализируем две ключевые причины, почему сервер не видит файлы по сетевым путям:

  1. Проблема «Сессии 0» (Session 0 Isolation). Служба сервера 1С:Предприятия работает в изолированной системной сессии Windows. В этой сессии физически не существует сетевых дисков, подключенных конкретными пользователями. Диск K:\ для сервера 1С просто не существует. Решением является обязательное использование полных сетевых путей в формате UNC: \\имя_сервера\имя_папки\имя_файла вместо букв дисков.
  2. Права учетной записи службы 1С (USR1CV8). По умолчанию служба сервера 1С запускается под локальной системной учетной записью USR1CV8. Этот пользователь не имеет доступа к сетевым ресурсам других серверов и компьютеров в домене. Платформа честно возвращает Ложь при попытке проверить существование файла, так как у процесса просто нет прав зайти в эту папку.

Разберем по шагам, как правильно преобразовать путь к файлу в коде и настроить права доступа.

Шаг 1. Преобразование локальных путей в формат UNC

Если в вашей базе хранятся пути с использованием локальных букв дисков, их необходимо динамически заменять на сетевые аналоги при выполнении кода на сервере. Рассмотрим пример кода:


// Неправильно для сервера: "K:\Bases\1Cv8.1CD"
// Правильно для сервера: "\\srv-sql\Bases\1Cv8.1CD"

ПутьКБазе = ВыборкаДетальныеЗаписи.ПутьКБазе;
ИмяФайла = СокрЛП(ПутьКБазе) + "1Cv8.1CD";

// Если код выполняется на сервере, заменяем букву диска на сетевой UNC-путь
Если НаСервере() Тогда
    ИмяФайла = СтрЗаменить(ИмяФайла, "K:\", "\\srv-sql\shared_folder\");
КонецЕсли;

ВыбФайл = Новый Файл(ИмяФайла);
Если ВыбФайл.Существует() Тогда
    РазмерФайла = ВыбФайл.Размер();
КонецЕсли;

Шаг 2. Системная настройка прав службы 1С:Предприятия

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

Загадка COM-соединения: почему при подключении файлы временно «видны»?

В процессе обсуждения авторы заметили странный эффект: если перед проверкой существования файла инициировать COM-подключение через V83.ComConnector, то файлы некоторых баз чудесным образом начинают определяться методом Существует() как истинные, а без подключения — нет.

Выясним причину этого феномена. Дело в механизме кэширования сетевых сессий Windows (SMB Session Caching):

Важно помнить: использовать создание тяжелого COM-объекта только ради того, чтобы «пробить» сетевой доступ к файлу — это крайне неоптимальный и грубый подход. Это приводит к утечкам памяти, блокировкам файлов (созданию файлов 1Cv8.1CL) и непредсказуемому поведению системы. Решать проблему нужно исключительно настройкой прав Windows на уровне сетевых папок!

Спорные методы: «Новый Файл()» против «НайтиФайлы()»

Среди разработчиков часто возникают споры о том, как правильнее проверять наличие файлов и их свойства. Некоторые утверждают, что использовать конструктор Новый Файл() — некорректно, и нужно использовать функцию НайтиФайлы(). Проанализируем эту ситуацию.

На самом деле, оба метода абсолютно легитимны, но они решают разные задачи:

Пример безопасного получения размера файла с обработкой возможных исключений:


Функция ПолучитьРазмерФайлаБезопасно(ПолныйПуть) Экспорт
    
    РезультирующийРазмер = 0;
    ФайловыйОбъект = Новый Файл(ПолныйПуть);
    
    Попытка
        Если ФайловыйОбъект.Существует() Тогда
            РезультирующийРазмер = ФайловыйОбъект.Размер();
        Иначе
            ЗаписьЖурналаРегистрации("Работа с файлами",
                УровеньЖурналаРегистрации.Предупреждение,
                , , 
                "Файл не найден по пути: " + ПолныйПуть);
        КонецЕсли;
    Исключение
        ЗаписьЖурналаРегистрации("Работа с файлами",
            УровеньЖурналаРегистрации.Ошибка,
            , , 
            "Ошибка доступа к файлу: " + ОписаниеОшибки());
    КонецПопытки;
    
    Возвращать РезультирующийРазмер;
    
КонецФункции

Почему размер файла в Табличной части равен «99»?

Рассмотрим еще одну распространенную техническую ошибку. Разработчик пытается выгрузить корректно определенный размер файла в табличную часть обработки или документа, однако вместо реального объема (например, 150 240 байт) на экране и в базе отображается число 99.

Причина кроется в ограничении длины числового типа данных в метаданных конфигурации:

Решение проблемы:

  1. Откройте конфигуратор вашей базы данных.
  2. Найдите нужный реквизит табличной части (или реквизит справочника/документа).
  3. Увеличьте длину реквизита минимум до 15 знаков с точностью 0. Это позволит корректно сохранять размеры файлов в байтах вплоть до терабайтных значений.
  4. В качестве альтернативного варианта — переводите размер файла из байтов в мегабайты перед выводом в интерфейс, используя формулу деления на 1 048 576 (1024 * 1024), и настройте точность реквизита в 2 знака после запятой.

Пример перевода байтов в мегабайты для записи в реквизит с точностью до двух знаков:


РазмерВБайтах = ВыбФайл.Размер(); // Например, 15728640 байт
РазмерВМегабайтах = Окр(РазмерВБайтах / (1024 * 1024), 2); // Результат: 15.00 Мб

СтрокаТЧ = Объект.ТабличнаяЧастьФайлов.Добавить();
СтрокаТЧ.ИмяФайла = ВыбФайл.Имя;
СтрокаТЧ.РазмерМБ = РазмерВМегабайтах; // Теперь число поместится корректно

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

← На главную