В практике разработки на платформе 1С:Предприятие 8.3 одной из самых распространенных задач является передача файла (например, реестра в формате Excel) с локального компьютера пользователя на сервер для последующей обработки. Казалось бы, задача тривиальная, однако при работе в клиент-серверном варианте, особенно через веб-сервер, разработчики часто сталкиваются с ошибкой «Доступ к файлу не может быть получен». В этой статье мы подробно разберем, почему возникает эта ошибка, и рассмотрим правильные алгоритмы передачи данных.
Проанализируем типичную ситуацию: клиентское приложение запущено на домашнем компьютере, а сервер 1С и база данных PostgreSQL находятся на удаленном сервере в дата-центре. Когда вы пытаетесь выполнить код Объект.ПутьКФайлу на сервере, система ищет этот путь в файловой системе сервера, а не вашего компьютера. Естественно, сервер «не видит» ваш диск C: или папку «Загрузки».
Основная причина ошибок кроется в двух аспектах:
КаталогВременныхФайлов() + ".xls", что часто приводит к созданию путей, на которые у серверного процесса (обычно это пользователь USR1CV8) нет прав записи.Рассмотрим, как правильно организовать этот процесс по шагам.
Для начала нам нужно получить содержимое файла на клиенте и «забросить» его в специальную область памяти на сервере — Временное хранилище. Рассмотрим современный асинхронный подход с использованием ОписаниеОповещения.
Разберем пример кода для выбора файла:
&НаКлиенте
Процедура ПутьКФайлуНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьВыборФайла", ЭтаФорма);
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ДиалогОткрытияФайла.Заголовок = "Выберите файл для загрузки";
ДиалогОткрытияФайла.Фильтр = "Файлы Excel (*.xls;*.xlsx)|*.xls;*.xlsx";
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
// Помещаем файл во временное хранилище сразу при выборе
НачатьПомещениеФайлов(ОписаниеОповещения, , ДиалогОткрытияФайла, Истина, УникальныйИдентификатор);
КонецПроцедуры
В данном фрагменте мы используем метод НачатьПомещениеФайлов. Важно обратить внимание на последний параметр — УникальныйИдентификатор формы. Это гарантирует, что файл будет жить в хранилище до тех пор, пока открыта наша форма.
После того как пользователь выбрал файл, сработает процедура оповещения. Выясним, как извлечь адрес файла:
&НаКлиенте
Процедура ОбработатьВыборФайла(ПомещенныеФайлы, ДополнительныеПараметры) Экспорт
Если ПомещенныеФайлы = Неопределено Тогда
Возврат; // Пользователь отменил выбор
КонецЕсли;
Для каждого ПереданныйФайл Из ПомещенныеФайлы Цикл
// Сохраняем адрес во временном хранилище в реквизит формы
Объект.АдресФайлаВоВременномХранилище = ПереданныйФайл.Хранение;
Объект.ИмяФайла = ПереданныйФайл.Имя;
Сообщить("Файл успешно подготовлен к передаче!");
КонецЦикла;
КонецПроцедуры
Теперь, когда у нас есть адрес в хранилище, мы можем обратиться к нему на сервере. Рассмотрим ситуацию, когда нам нужно прочитать Excel-файл и преобразовать его в таблицу значений. Проанализируем пример функции, которая выполняет эту операцию:
&НаСервере
Функция ПрочитатьФайлНаСервере(АдресХранилища, РасширениеФайла)
// 1. Извлекаем двоичные данные из хранилища
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
// 2. Создаем уникальное имя временного файла на сервере
// ВАЖНО: Используйте ПолучитьИмяВременногоФайла с указанием расширения
ИмяВременногоФайла = ПолучитьИмяВременногоФайла(РасширениеФайла);
// 3. Записываем данные на диск сервера
ДвоичныеДанные.Записать(ИмяВременногоФайла);
Попытка
// Читаем файл, например, через ТабличныйДокумент
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяВременногоФайла);
// Далее идет логика обработки ТабДока...
Возврат "Файл прочитан успешно, строк: " + ТабДок.ВысотаТаблицы;
Исключение
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Ошибка при чтении файла: " + ОписаниеОшибки());
Возврат Неопределено;
Наконец
// 4. Обязательно удаляем временный файл после работы!
УдалитьФайлы(ИмяВременногоФайла);
КонецПопытки;
КонецФункции
Если ваша база опубликована через IIS или Apache, стандартных механизмов 1С может быть недостаточно из-за ограничений безопасности веб-сервера. Разберем основные моменты:
IUSR или DefaultAppPool), есть права на чтение и запись в папку временных файлов системы (C:\Windows\Temp).maxAllowedContentLength в настройках IIS.Прочитать объекта ТабличныйДокумент для файлов XLSX требует наличия установленных шрифтов (пакет ttf-mscorefonts-installer) и библиотеки fontconfig. Без них вы получите неочевидную ошибку чтения.Начиная с версии 8.3.15, рекомендуется использовать метод НачатьПомещениеФайлаНаСервер. Это позволяет более гибко управлять процессом загрузки и получать прогресс передачи данных. Посмотрим на упрощенную схему:
&НаКлиенте
Процедура ЗагрузитьФайлНовымМетодом()
ПараметрыЗагрузки = Новый ПараметрыПомещенияФайлаНаСервер;
ПараметрыЗагрузки.Интерактивно = Истина;
ОписаниеОповещения = Новый ОписаниеОповещения("ЗавершениеЗагрузки", ЭтотОбъект);
НачатьПомещениеФайлаНаСервер(ОписаниеОповещения, , , ПараметрыЗагрузки, УникальныйИдентификатор);
КонецПроцедуры
Этот метод возвращает объект ОписаниеПереданногоФайла, который содержит уже готовый адрес во временном хранилище и всю метаинформацию о файле (имя, размер), что избавляет нас от необходимости вручную разбирать массивы в цикле.
Подведем итог: никогда не передавайте на сервер путь к файлу строкой, если клиент и сервер — это разные машины. Всегда используйте Временное хранилище и метод ПолучитьИмяВременногоФайла() с явным указанием расширения. Это обеспечит стабильную работу вашей обработки в любых условиях эксплуатации.