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

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

При работе с файлами Microsoft Excel на стороне сервера в среде 1С:Предприятие 8.3 программисты часто сталкиваются с неочевидной ошибкой: «Ошибка при выполнении операции... Доступ к файлу не может быть получен». Эта проблема может сбивать с толку, так как она часто проявляется избирательно — например, файлы .mxl открываются без проблем, а современные форматы .xlsx вызывают сбой. Проанализируем причины этой ситуации и разберем пошагово методы её решения.

Разбор основной причины: Влияние расширения файла на парсер 1С

Рассмотрим ситуацию, представленную в обсуждении. Программист передает файл с клиента на сервер через временное хранилище, а затем сохраняет его на диск сервера, используя метод ПолучитьИмяВременногоФайла("xls"). Именно здесь кроется критическая ошибка. Проанализируем, как работает метод ТабличныйДокумент.Прочитать(). Платформа 1С использует расширение файла в качестве подсказки для выбора внутреннего алгоритма (парсера), который будет обрабатывать структуру данных.

Если мы сохраняем файл формата OpenXML (xlsx) с расширением .xls, система пытается прочитать его как старый бинарный формат BIFF8 (Excel 97-2003). В результате несоответствия внутренней структуры и ожидаемого формата платформа выдает ошибку доступа. Это происходит потому, что чтение прерывается на низком уровне, и операционная система или сама платформа интерпретирует это как невозможность корректно захватить дескриптор файла.

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


// На стороне клиента получаем расширение
лстр_ПолноеИмяФайла = ИмяФайла; // Путь, выбранный пользователем
ТекФайл = Новый Файл(лстр_ПолноеИмяФайла);
лстр_Расширение = ТекФайл.Расширение; // Например, ".xlsx"

// Передаем файл и расширение на сервер
ДвоичныеДанные = Новый ДвоичныеДанные(лстр_ПолноеИмяФайла);
Адрес = ПоместитьВоВременноеХранилище(ДвоичныеДанные);
Результат = ПрочитатьФайлНаСервере(Адрес, лстр_Расширение);

Теперь на сервере мы должны использовать это расширение (убрав точку, если необходимо), чтобы временный файл соответствовал оригиналу:


&НаСервере
Функция ПрочитатьФайлНаСервере(Адрес, лстр_Расширение)
    // Убираем точку из расширения для метода ПолучитьИмяВременногоФайла
    ЧистоеРасширение = СтрЗаменить(лстр_Расширение, ".", "");
    лстр_ИмяФайла = ПолучитьИмяВременногоФайла(ЧистоеРасширение);
    
    ДанныеХранилища = ПолучитьИзВременногоХранилища(Адрес);
    ДанныеХранилища.Записать(лстр_ИмяФайла);
    
    ТабДок = Новый ТабличныйДокумент;
    Попытка
        ТабДок.Прочитать(лстр_ИмяФайла);
    Исключение
        ЗаписьЖурналаРегистрации("ЧтениеФайла", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
        Возврат Неопределено;
    КонецПопытки;
    
    // Важно: всегда удаляйте временные файлы после использования!
    УдалитьФайлы(лстр_ИмяФайла);
    
    Возврат ТабДок;
КонецФункции

Оптимизация архитектуры: Избавляемся от лишних дисковых операций

Проанализируем структуру кода дальше. Часто разработчики разделяют процесс на «сохранение» и «чтение», опасаясь, что файл не успеет «освободиться» после записи. Однако в 1С:Предприятие 8.3 операции выполняются последовательно. Более того, на современных версиях платформы (начиная с 8.3.10) можно полностью избежать записи файла на диск сервера, что решает проблемы с правами доступа к папке Temp.

Выясним причину, почему работа через поток лучше: метод ТабличныйДокумент.Прочитать() может принимать в качестве параметра поток (объект ЧтениеДанных). Это позволяет обрабатывать файл целиком в оперативной памяти.

Рассмотрим пример реализации без создания временного файла на диске:


&НаСервере
Функция ПрочитатьФайлВПамяти(АдресХранилища)
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
    
    // Создаем поток из двоичных данных
    Поток = ДвоичныеДанные.ОткрытьПотокДляЧтения();
    ТабДок = Новый ТабличныйДокумент;
    
    Попытка
        // Платформа сама определит тип данных внутри потока
        ТабДок.Прочитать(Поток);
    Исключение
        Сообщить("Ошибка чтения: " + ОписаниеОшибки());
    КонецПопытки;
    
    Поток.Закрыть();
    Возврат ТабДок;
КонецФункции

Проверка прав доступа учетной записи службы 1С

Если расширение указано верно, но ошибка «Доступ к файлу не может быть получен» сохраняется, нам необходимо проверить системные настройки сервера. Служба «1C:Enterprise 8.3 Server Agent» запускается от имени определенного пользователя (обычно USR1CV8 в Windows или usr1cv8 в Linux).

Проанализируем следующие моменты:

  1. Права на временную директорию: Учетная запись службы должна иметь полные права (Чтение, Запись, Модификация) на папку, которую возвращает функция ПолучитьИмяВременногоФайла(). В Windows это обычно C:\Windows\Temp или профиль пользователя службы AppData\Local\Temp.
  2. Блокировка антивирусом: Серверные антивирусы часто сканируют файлы в момент их создания. Когда 1С вызывает Записать(), антивирус может мгновенно захватить файл для проверки, и в этот же миг метод Прочитать() получает отказ в доступе. Рекомендуется добавить временные папки 1С в исключения антивируса.
  3. Лимиты файловой системы: В папке временных файлов может накопиться критическое количество старых .tmp файлов (более 65 тысяч). В таком случае создание нового файла может завершиться ошибкой доступа. Периодическая очистка Temp — обязанность системного администратора.

Особенности работы на Linux-серверах

Если ваш сервер 1С работает под управлением Linux, следует учитывать специфику этой ОС. Разберем важные нюансы:

Проблемы «Legacy» форматов (Excel 2.1 и файлы из 1С 7.7)

Выясним причину еще одного типа сбоев. Файлы, сформированные в старых системах (например, 1С:Предприятие 7.7) или сторонним ПО, могут иметь расширение .xls, но фактически являться HTML-документами или очень старыми бинарными форматами (Excel 2.1).

Современный ТабличныйДокумент в версии 8.3 может отказаться читать такие файлы через стандартный метод Прочитать(). Если вы столкнулись с сообщением «Формат файла не поддерживается», единственным надежным способом будет предварительное открытие такого файла в MS Excel и его пересохранение в формат Excel 2007+ (xlsx). На серверах под управлением Windows это можно автоматизировать через COM-объект Excel.Application, но помните, что это требует установленного Microsoft Office на сервере и настройки прав в DCOMCNFG.

Подводя итог, можно сказать, что в 90% случаев ошибка доступа к Excel-файлу на сервере решается простым контролем соответствия расширения временного файла исходному расширению загружаемого документа. Использование потоков (ЧтениеДанных) является более современным и надежным методом, который мы рекомендуем внедрять во все новые разработки.

← На главную