Почему внешние обработки ЗУП 3.0 не создают файлы при публикации через веб-сервер?

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

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

Изначально, в файловом режиме, внешняя обработка могла напрямую взаимодействовать с локальной файловой системой компьютера пользователя, создавая, читая или записывая файлы. Однако, когда мы публикуем информационную базу через веб-сервер и запускаем ее в веб-клиенте (браузере), картина кардинально меняется. Веб-клиент не имеет прямого доступа к файловой системе пользовательского компьютера из соображений безопасности. Все операции с файлами должны выполняться через сервер 1С:Предприятия.

Выясняем причину: Ограничения веб-клиента и клиент-серверное взаимодействие

Основная причина, по которой внешние обработки перестают создавать файлы в веб-клиенте, кроется в архитектурных особенностях. Веб-клиент — это, по сути, страница в браузере, которая общается с сервером 1С. Браузеры по умолчанию запрещают веб-страницам прямой доступ к локальным дискам пользователя, чтобы предотвратить вредоносные действия. Таким образом, любая попытка кода, исполняющегося в контексте веб-клиента, создать или записать файл напрямую на диск пользователя потерпит неудачу.

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

Разделение кода: Клиентский и серверный контекст

Для корректной работы в управляемом приложении (к которому относится ЗУП 3.0 и веб-клиент) критически важно правильно разделять код на клиентский и серверный. Это достигается с помощью директив компиляции:

  1. &НаКлиенте: Код, который выполняется на клиентской стороне (в браузере для веб-клиента или на компьютере пользователя для тонкого клиента). Он не имеет доступа к серверным объектам и файловой системе сервера.
  2. &НаСервере: Код, который выполняется на сервере 1С:Предприятия. Он имеет доступ к файловой системе сервера, информационной базе, а также к серверным объектам.
  3. &НаКлиентеНаСервере: Код, который может выполняться как на клиенте, так и на сервере. Часто используется для общих функций, которые не зависят от контекста выполнения.

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

Решение проблемы: Использование механизма временного хранилища для файлов

Для обмена файлами между сервером и клиентом в 1С используется специальный механизм — временное хранилище. Это позволяет серверу создать файл, поместить его во временное хранилище, а затем передать клиенту ссылку на этот файл. Клиент, получив ссылку, может инициировать скачивание файла.

Шаг 1: Формирование файла на сервере

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

Предположим, у нас есть кнопка на форме обработки, по нажатию на которую должен быть создан файл.


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

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

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

Пояснения к коду:

  1. Процедура КомандаСформироватьФайл выполняется на клиенте. Она вызывает серверную функцию для формирования файла.
  2. Функция СформироватьФайлНаСервере выполняется на сервере. Здесь мы:
    1. Получаем временное имя файла на сервере с помощью ПолучитьИмяВременногоФайла().
    2. Создаем объект ТекстовыйДокумент (или любой другой, например, ДвоичныеДанные, ТабличныйДокумент), заполняем его данными и записываем в файл на диске сервера.
    3. С помощью функции ПоместитьФайлВоВременноеХранилище() мы перемещаем созданный на сервере файл во внутреннее временное хранилище 1С и получаем его уникальный адрес. Этот адрес и будет передан на клиент.
    4. Важно: После помещения файла во временное хранилище, мы удаляем его с диска сервера, чтобы не засорять дисковое пространство.
  3. После возвращения на клиент, если адрес временного хранилища не пустой, мы используем функцию НачатьПолучениеФайлаССервера(). Эта функция асинхронно инициирует загрузку файла с сервера на клиент.
  4. Мы передаем в НачатьПолучениеФайлаССервера():
    1. Адрес файла во временном хранилище.
    2. Объект ОписаниеПередачиФайла, который содержит рекомендуемое имя файла для сохранения на клиенте. Пользователь увидит это имя в диалоге сохранения.
    3. Объект ОписаниеОповещения, который указывает на процедуру (ПослеПолученияФайлаССервера) и объект, который эту процедуру содержит. Эта процедура будет вызвана после завершения операции сохранения файла на клиенте, сообщая нам о ее результате.
  5. Процедура ПослеПолученияФайлаССервера также выполняется на клиенте и обрабатывает результат сохранения файла.

Шаг 2: Работа с двоичными данными

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


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

Дальнейший вызов НачатьПолучениеФайлаССервера будет таким же, как и для текстового файла.

Дополнительные аспекты и возможные проблемы

Расширение работы с файлами

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

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

Права доступа и настройки веб-сервера

Иногда проблемы с внешними обработками могут быть связаны не только с кодом, но и с окружением. Убедитесь, что пользователь, от имени которого работает веб-сервер (например, IIS или Apache), имеет достаточные права доступа:

  1. К каталогу с файлами платформы 1С: Для чтения и выполнения (папка bin).
  2. К каталогу информационной базы: Особенно в файловом варианте публикации (если база не клиент-серверная, но публикуется через веб-сервер), для чтения и записи.
  3. К временным каталогам на сервере: Процесс 1С может использовать системные временные каталоги для промежуточных файлов. У пользователя веб-сервера должны быть права на чтение/запись в эти каталоги.

Если веб-сервер настроен неправильно или есть проблемы с правами, даже идеально написанный код не сможет создать или записать файл на сервере.

Проверка логов веб-сервера и журнала регистрации 1С

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

  1. Журнал регистрации 1С:Предприятия: Он может содержать подробные сообщения об ошибках, возникших при выполнении серверного кода, в том числе при попытке работы с файлами.
  2. Логи веб-сервера (IIS или Apache): Эти логи могут указать на проблемы с публикацией, доступом или выполнением запросов, особенно если запрос даже не доходит до сервера 1С.

Итоговый алгоритм для адаптации внешней обработки

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

  1. Идентифицируйте код, работающий с файлами: Найдите все участки кода, которые отвечают за формирование содержимого файла и его запись на диск.
  2. Перенесите формирование файла на сервер: Весь этот код должен быть помещен в процедуру или функцию, помеченную директивой &НаСервере.
  3. Используйте временное хранилище: После создания файла на сервере, используйте функцию ПоместитьФайлВоВременноеХранилище(), чтобы получить адрес, по которому клиент сможет забрать файл. Не забудьте удалить временный файл с сервера после помещения в хранилище.
  4. Инициируйте загрузку на клиент: На клиентской стороне, после получения адреса временного хранилища, вызовите функцию НачатьПолучениеФайлаССервера(), передав ей адрес и описание файла.
  5. Обработайте результат: Предусмотрите процедуру-обработчик (через ОписаниеОповещения) для получения информации об успешности или ошибке сохранения файла на клиенте.
  6. Проверьте права и настройки: Убедитесь, что веб-сервер и пользователь, от имени которого он работает, имеют необходимые права доступа к файловым ресурсам сервера.

Следуя этим рекомендациям, вы сможете адаптировать ваши внешние обработки для корректной работы в условиях веб-клиента и обеспечить стабильное формирование и передачу файлов пользователям ЗУП 3.0.

← На главную