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

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

В практике разработки на платформе 1С:Предприятие 8.3 одной из самых распространенных задач является передача файла (например, реестра в формате Excel) с локального компьютера пользователя на сервер для последующей обработки. Казалось бы, задача тривиальная, однако при работе в клиент-серверном варианте, особенно через веб-сервер, разработчики часто сталкиваются с ошибкой «Доступ к файлу не может быть получен». В этой статье мы подробно разберем, почему возникает эта ошибка, и рассмотрим правильные алгоритмы передачи данных.

Почему возникает ошибка доступа?

Проанализируем типичную ситуацию: клиентское приложение запущено на домашнем компьютере, а сервер 1С и база данных PostgreSQL находятся на удаленном сервере в дата-центре. Когда вы пытаетесь выполнить код Объект.ПутьКФайлу на сервере, система ищет этот путь в файловой системе сервера, а не вашего компьютера. Естественно, сервер «не видит» ваш диск C: или папку «Загрузки».

Основная причина ошибок кроется в двух аспектах:

  1. Разрыв контекста: Попытка передать на сервер только строку с путем к файлу вместо самого содержимого файла.
  2. Некорректное формирование временных имен: Использование прямой склейки строк вида КаталогВременныхФайлов() + ".xls", что часто приводит к созданию путей, на которые у серверного процесса (обычно это пользователь USR1CV8) нет прав записи.

Рассмотрим, как правильно организовать этот процесс по шагам.

Шаг 1. Выбор файла на клиенте и помещение во временное хранилище

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

Разберем пример кода для выбора файла:


&НаКлиенте
Процедура ПутьКФайлуНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьВыборФайла", ЭтаФорма);
    ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    ДиалогОткрытияФайла.Заголовок = "Выберите файл для загрузки";
    ДиалогОткрытияФайла.Фильтр = "Файлы Excel (*.xls;*.xlsx)|*.xls;*.xlsx";
    ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
    
    // Помещаем файл во временное хранилище сразу при выборе
    НачатьПомещениеФайлов(ОписаниеОповещения, , ДиалогОткрытияФайла, Истина, УникальныйИдентификатор);
КонецПроцедуры

В данном фрагменте мы используем метод НачатьПомещениеФайлов. Важно обратить внимание на последний параметр — УникальныйИдентификатор формы. Это гарантирует, что файл будет жить в хранилище до тех пор, пока открыта наша форма.

Шаг 2. Обработка результата выбора

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


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

Шаг 3. Чтение файла на стороне сервера

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


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

Важные нюансы при работе с веб-сервером

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

  1. Права доступа: Убедитесь, что у пользователя, под которым запущен пул приложений веб-сервера (например, IUSR или DefaultAppPool), есть права на чтение и запись в папку временных файлов системы (C:\Windows\Temp).
  2. Размер файла: Если вы передаете файлы объемом более 30 МБ, веб-сервер может оборвать соединение. Проверьте параметр maxAllowedContentLength в настройках IIS.
  3. Linux-серверы: Если сервер 1С работает на Linux, помните, что метод Прочитать объекта ТабличныйДокумент для файлов XLSX требует наличия установленных шрифтов (пакет ttf-mscorefonts-installer) и библиотеки fontconfig. Без них вы получите неочевидную ошибку чтения.

Использование современных методов (Платформа 8.3.15+)

Начиная с версии 8.3.15, рекомендуется использовать метод НачатьПомещениеФайлаНаСервер. Это позволяет более гибко управлять процессом загрузки и получать прогресс передачи данных. Посмотрим на упрощенную схему:


&НаКлиенте
Процедура ЗагрузитьФайлНовымМетодом()
    ПараметрыЗагрузки = Новый ПараметрыПомещенияФайлаНаСервер;
    ПараметрыЗагрузки.Интерактивно = Истина;
    
    ОписаниеОповещения = Новый ОписаниеОповещения("ЗавершениеЗагрузки", ЭтотОбъект);
    
    НачатьПомещениеФайлаНаСервер(ОписаниеОповещения, , , ПараметрыЗагрузки, УникальныйИдентификатор);
КонецПроцедуры

Этот метод возвращает объект ОписаниеПереданногоФайла, который содержит уже готовый адрес во временном хранилище и всю метаинформацию о файле (имя, размер), что избавляет нас от необходимости вручную разбирать массивы в цикле.

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

← На главную