Как решить проблему передачи объекта XBase между клиентом и сервером в 1С:Предприятии

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

При разработке в среде 1С:Предприятие 8 на управляемых формах программисты часто сталкиваются с необходимостью интеграции со сторонними информационными системами посредством обмена файлами формата DBF. Для работы с ними платформа предлагает стандартный и удобный объект XBase. Однако при попытке передать созданный на клиенте объект XBase в качестве параметра процедуры на сервере возникает критическая ошибка: «Ошибка преобразования данных XDTO: Запись значения свойства... Отсутствует отображение для типа 'XBase'».

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

Выясняем причину: почему возникает ошибка отображения типов?

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

Сериализация — это процесс преобразования внутреннего объекта платформы в поток данных (обычно в формате XML/XDTO или JSON), который можно физически передать по сети между процессами клиента и сервера. На принимающей стороне происходит обратный процесс — десериализация.

Объект XBase является низкоуровневой системной оберткой над физическим файлом базы данных DBF, находящимся на диске. Этот объект содержит ссылки на открытые файловые дескрипторы операционной системы и жестко привязан к среде исполнения. Разработчикам платформы не имело смысла реализовывать сериализацию для данного типа, так как невозможно передать открытый системный дескриптор файла по сети. Именно поэтому XBase не поддерживает сериализацию. Попытка передать его на сервер напрямую или поместить во временное хранилище всегда будет заканчиваться ошибкой отображения типов XDTO.

Правильный паттерн работы: передача через двоичные данные

Что же делать, если файл DBF физически находится на компьютере пользователя (на клиенте), а вся бизнес-логика по его чтению и обработке должна выполняться на сервере 1С? В клиент-серверном режиме у сервера нет прямого доступа к локальным дискам клиентской машины (например, к диску C:\ пользователя).

Единственным архитектурно верным решением в данном случае является передача не самого объекта XBase, а непосредственно тела файла в виде двоичных данных через временное хранилище платформы 1С. Рассмотрим эту схему подробнее:

  1. На стороне клиента: Мы берем локальный файл DBF с диска пользователя, считываем его содержимое в объект ДвоичныеДанные и помещаем этот объект во временное хранилище. Нам возвращается уникальный адрес (навигационная ссылка) во временном хранилище.
  2. Вызов сервера: Передаем полученный адрес (строку) в качестве параметра серверной функции. Строковый адрес прекрасно сериализуется и проходит границу «клиент-сервер».
  3. На стороне сервера:
    • Извлекаем из временного хранилища объект ДвоичныеДанные по переданному адресу.
    • Создаем временный файл в файловой системе сервера при помощи метода ПолучитьИмяВременногоФайла().
    • Записываем двоичные данные в этот временный файл.
    • Создаем локальный серверный объект Новый XBase, открываем наш временный файл, считываем или изменяем нужные данные.
    • Если файл модифицировался, считываем измененный файл обратно в ДвоичныеДанные и помещаем результат в новое временное хранилище, возвращая адрес клиенту.
    • Важно: Обязательно удаляем за собой временный файл на сервере, чтобы избежать засорения дискового пространства.
  4. Снова на клиенте: Извлекаем двоичные данные по возвращенному адресу и записываем их поверх исходного файла на клиенте.

Реализация схемы в коде

Давайте посмотрим на практический пример реализации данного алгоритма. Ниже представлен готовый шаблон кода, который вы можете использовать в своих обработках:


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

// НА СТОРОНЕ СЕРВЕРА
&НаСервереБезКонтекста
Функция ОбработатьФайлНаСервере(Знач АдресВХранилище)
    
    // 1. Извлекаем бинарные данные файла из хранилища
    ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(АдресВХранилище);
    
    // 2. Генерируем уникальное имя файла во временном каталоге сервера
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("dbf");
    
    // 3. Сохраняем двоичные данные на диск сервера
    ДвоичныеДанныеФайла.Записать(ИмяВременногоФайла);
    
    // 4. Инициализируем и работаем с XBase исключительно на сервере
    БД = Новый XBase;
    
    Попытка
        БД.ОткрытьФайл(ИмяВременногоФайла);
        
        Если Не БД.Открыта() Тогда
            ВызватьИсключение "Не удалось открыть DBF-файл на сервере.";
        КонецЕсли;
        
        // Переходим к первой записи и производим необходимые манипуляции
        БД.Первая();
        Пока Не БД.В Конце() Цикл
            
            // Пример модификации данных
            // БД.ИмяПоля = "Новое значение";
            // БД.Записать();
            
            БД.Следующая();
        КонецЦикла;
        
        // Также мы можем добавить новую запись
        БД.Добавить();
        БД.УстановитьЗначениеПоля("USER_ID", 101);
        БД.УстановитьЗначениеПоля("STATUS", "Обработано на сервере");
        БД.Записать();
        
        БД.ЗакрытьФайл();
        
    Исключение
        // В случае ошибки закрываем файл и удаляем его, чтобы не блокировать ресурсы
        Если БД.Открыта() Тогда
            БД.ЗакрытьФайл();
        КонецЕсли;
        УдалитьФайлы(ИмяВременногоФайла);
        ВызватьИсключение КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
    КонецПопытки;
    
    // 5. Помещаем измененный файл обратно в хранилище для передачи на клиент
    НовыеДвоичныеДанные = Новый ДвоичныеДанные(ИмяВременногоФайла);
    АдресРезультата = ПоместитьВоВременноеХранилище(НовыеДвоичныеДанные);
    
    // 6. Обязательно производим очистку временных файлов на сервере
    УдалитьФайлы(ИмяВременногоФайла);
    
    Возврат АдресРезультата;
    
ФункцияКонец

Альтернативный вариант: вся логика на стороне клиента

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

Выясним, как упростить процесс:

  1. Формируем на сервере простую коллекцию данных (например, массив структур или таблицу значений). Эти типы данных прекрасно сериализуются и могут быть переданы с сервера на клиент.
  2. Передаем эту коллекцию данных на клиент.
  3. На клиенте создаем объект Новый XBase, открываем локальный файл и в цикле переносим данные из полученной коллекции непосредственно в DBF-файл. Запись происходит локально на диске пользователя.

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

Критическое ограничение: работа на серверах под управлением Linux

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

Полное отсутствие поддержки XBase на 64-битных Linux-серверах: Платформа 1С:Предприятие на текущий момент принципиально не поддерживает инициализацию и работу объекта XBase в 64-разрядных рабочих процессах под ОС Linux. Попытка выполнить конструкцию БД = Новый XBase; на стороне такого сервера приведет к ошибке инициализации объекта или аварийному завершению работы процесса.

Если ваша информационная база крутится на Linux-сервере, у вас есть три пути решения этой проблемы:

Также помните, что файловая система Linux, в отличие от Windows, крайне чувствительна к регистру символов (case-sensitive). При создании файлов или путей на сервере Linux всегда следите за тем, чтобы расширение файла (например, .dbf или .DBF) совпадало во всех методах открытия и создания файлов.

Резюме

Мы подробно разобрали проблему передачи объекта XBase в клиент-серверной архитектуре 1С. Запомните главное правило: никогда не пытайтесь передавать сложные системные объекты, привязанные к файловой системе или оборудованию, через границу клиент-сервера. Используйте универсальный транспорт платформы — ДвоичныеДанные и Временное хранилище. Это сделает ваш код стабильным, производительным и избавит от трудночитаемых ошибок отображения типов XDTO.

← На главную