При разработке внешних отчетов или обработок в среде 1С часто возникает ситуация, когда в файловом варианте базы данных все работает идеально, но при переходе в клиент-серверный режим программа выдает ошибку: «Каталог не обнаружен». Проанализируем причину этой проблемы: она заключается в разделении контекста исполнения кода. Когда пользователь выбирает файл на своем компьютере (на клиенте), путь к нему выглядит как локальный адрес (например, C:\Users\Documents\data.xlsx). Однако сервер 1С, на котором выполняется основная логика отчета, «не видит» файловую систему пользователя. Для сервера этот путь либо не существует, либо ведет к его собственным локальным дискам.
Разберем по шагам, как правильно организовать передачу файла с клиента на сервер и его последующее чтение, используя современные методики платформы 8.3.
Это классический и наиболее надежный способ. Основная идея заключается в том, чтобы превратить файл в объект типа ДвоичныеДанные на стороне клиента, поместить его в специальное временное хранилище 1С и передать серверу только уникальный адрес (ссылку) на эти данные.
Рассмотрим пример кода на стороне клиента (в модуле формы отчета):
&НаКлиенте
Процедура ВыбратьИПрочитатьФайл(Команда)
// Диалог выбора файла
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл для загрузки";
Если Диалог.Выбрать() Тогда
ВыбранныйФайл = Диалог.ПолноеИмяФайла;
// Помещаем файл во временное хранилище
// Используем УникальныйИдентификатор формы, чтобы данные не удалились преждевременно
АдресФайла = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ВыбранныйФайл), ЭтаФорма.УникальныйИдентификатор);
// Вызываем серверную процедуру, передавая адрес
ПрочитатьФайлНаСервере(АдресФайла);
КонецЕсли;
КонецПроцедуры
Теперь проанализируем, что происходит на стороне сервера. Сервер получает адрес, извлекает данные и может либо записать их во временный файл на диске сервера, либо работать с ними напрямую (например, через ТабличныйДокумент).
&НаСервере
Процедура ПрочитатьФайлНаСервере(АдресФайла)
// Получаем двоичные данные из хранилища
ДанныеФайла = ПолучитьИзВременногоХранилища(АдресФайла);
Если ДанныеФайла <> Неопределено Тогда
// Вариант А: Чтение табличного документа напрямую из данных
ТабДок = Новый ТабличныйДокумент;
// Создаем поток из двоичных данных (доступно в новых версиях платформы)
Чтение = Новый ЧтениеДанных(ДанныеФайла);
ТабДок.Прочитать(Чтение, СпособЧтенияЗначенийТабличногоДокумента.Значение);
// Вариант Б: Если нужно сохранить файл на диске сервера для внешних утилит
ИмяВременногоФайлаСервер = ПолучитьИмяВременногоФайла("xlsx");
ДанныеФайла.Записать(ИмяВременногоФайлаСервер);
// ... выполняем логику обработки ...
// Обязательно удаляем временный файл после работы
УдалитьФайлы(ИмяВременногоФайлаСервер);
КонецЕсли;
КонецПроцедуры
Выясним важный нюанс: современные типовые конфигурации (ЗУП 3.1, ЗГУ 3.1, ERP) часто запускают формирование отчетов в фоновых заданиях. В этом случае временное хранилище, привязанное к форме, может быть недоступно фоновому заданию, так как оно выполняется в другом сеансе. Чтобы избежать ошибки, при использовании ПоместитьВоВременноеХранилище в качестве второго параметра следует передавать не идентификатор формы, а фиксированный идентификатор, который будет доступен фоновому заданию, либо передавать сам адрес хранилища в параметры фонового задания.
Если ваша конфигурация построена на БСП (как ЗГУ 3.1), мы рекомендуем использовать готовые методы подсистемы РаботаСФайлами. Это гарантирует корректную работу даже в веб-клиенте и мобильном приложении. Рассмотрим использование метода ФайловаяСистемаКлиент.ЗагрузитьФайл. Этот метод работает асинхронно, что соответствует современным требованиям платформы (отказ от модальных окон).
&НаКлиенте
Процедура ЗагрузитьФайлБСП(Команда)
ПараметрыЗагрузки = ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла();
ПараметрыЗагрузки.Заголовок = "Выберите файл данных";
Оповещение = Новый ОписаниеОповещения("ПослеЗагрузкиФайла", ЭтотОбъект);
ФайловаяСистемаКлиент.ЗагрузитьФайл(Оповещение, ПараметрыЗагрузки);
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗагрузкиФайла(Результат, ДополнительныеПараметры) Экспорт
Если Результат <> Неопределено Тогда
// Результат.Адрес содержит ссылку на временное хранилище
ОбработатьФайлНаСервере(Результат.Адрес);
КонецЕсли;
КонецПроцедуры
ПолучитьИмяВременногоФайла() всегда используйте блок Попытка...Исключение, чтобы гарантированно удалить файл в блоке завершения. Сервер 1С не очищает временные файлы автоматически мгновенно, и при большом объеме данных диск может переполниться.usr1cv8) должна иметь права на чтение и запись в папку временных файлов операционной системы сервера.ПоместитьВоВременноеХранилище может вызвать значительную нагрузку на сеть между клиентом и сервером. В таких случаях рассмотрите возможность предварительной обработки (фильтрации) данных прямо на клиенте, если это технически возможно (например, чтение текстового файла построчно)..ini или .txt) можно рассмотреть вариант чтения файла в строку на клиенте и передачу этой строки параметром в серверную функцию. Это избавит от работы с двоичными данными.Подведем итог: для успешного чтения файла во внешнем отчете в клиент-серверном режиме необходимо перенести данные из локальной файловой системы пользователя в область, доступную серверу 1С. Использование ДвоичныеДанные в сочетании с ВременнымХранилищем является «золотым стандартом» решения этой задачи.