Как исправить выгрузку DBF-файлов при переходе 1С:ЗУП на клиент-серверный режим (SQL)

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

Перевод информационной базы 1С с файлового режима работы на клиент-серверный (SQL) — это важный шаг для повышения производительности и отказоустойчивости системы. Однако этот процесс практически всегда сопровождается выявлением скрытых ошибок в старом коде программных модулей. Наиболее уязвимыми оказываются процедуры импорта и экспорта внешних файлов, включая работу с форматом DBF через объект XBase.

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

Выясняем причину: почему старый код перестал работать?

В файловом режиме работы 1С вся логика — и клиентская, и серверная — выполняется на одном и том же физическом компьютере пользователя. Переменные типа «путь к файлу» (например, C:\MyFolder\file.dbf) указывают на локальный диск текущего компьютера. Объект XBase на «сервере» без проблем находил файл по указанному пути, поскольку физический сервер и клиент были объединены в рамках одного процесса.

При переходе на клиент-серверную архитектуру ситуация кардинально меняется:

Концепция решения: использование Временного Хранилища

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

  1. На сервере создается пустой временный файл в специальной системной папке сервера.
  2. Объект XBase заполняет этот файл данными на стороне сервера.
  3. Готовый файл считывается в объект ДвоичныеДанные.
  4. Двоичные данные помещаются во временное хранилище с получением уникального адреса (строки).
  5. Временный файл на сервере физически удаляется, чтобы не засорять диск.
  6. Адрес хранилища передается обратно на клиент.
  7. Клиентское приложение забирает двоичные данные из хранилища и сохраняет их в файл на диске пользователя.

Важные нюансы формата DBF и кроссплатформенности

Разберем две критические проблемы, о которых забывают начинающие разработчики:

1. Длина имени файла (стандарт DOS 8.3). Объект XBase исторически чувствителен к длине имени файла и путям к нему. Если использовать стандартную функцию платформы ПолучитьИмяВременногоФайла("dbf"), она сгенерирует очень длинный путь, содержащий GUID (например, C:\Windows\Temp\v8_1A2B_3C.dbf). При записи или индексации такого файла 1С может выдать непредсказуемую ошибку. Поэтому имя временного файла на сервере рекомендуется формировать вручную, обрезая уникальный идентификатор до 8 символов.

2. Использование системного каталога временных файлов. Никогда не используйте жестко прописанные пути вроде "/tmp/" или "C:\Temp". Всегда вызывайте функцию КаталогВременныхФайлов(), которая автоматически вернет корректный путь для текущей операционной системы сервера (будь то Windows или Linux) с учетом прав доступа службы 1С.

Решение 1. Реализация на чистой платформе 1С (без использования БСП)

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

Создадим на сервере функцию, которая выполнит генерацию файла, запишет его во временное хранилище и удалит «следы» на сервере:


&НаСервере
Функция СформироватьDBFНаСервере()
    
    // Шаг 1. Генерируем уникальное имя файла по стандарту 8.3 для XBase
    УникальныйХвост = Лев(СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", ""), 8);
    ИмяФайлаНаСервере = КаталогВременныхФайлов() + УникальныйХвост + ".dbf";
    
    // Шаг 2. Инициализируем XBase и создаем структуру файла
    XBase = Новый XBase;
    XBase.Поля.Добавить("p8", "N", 15, 2);
    XBase.Кодировка = КодировкаXBase.ANSI;
    
    XBase.СоздатьФайл(ИмяФайлаНаСервере);
    
    // Здесь должен быть ваш код заполнения таблицы DBF
    // Пример добавления записи:
    XBase.Добавить();
    XBase.p8 = 150.50;
    XBase.Записать();
    
    // Обязательно закрываем файл, чтобы освободить дескриптор в операционной системе
    XBase.ЗакрытьФайл(); 
    
    // Шаг 3. Читаем файл в двоичные данные и помещаем в хранилище
    ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ИмяФайлаНаСервере);
    АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла);
    
    // Шаг 4. Очищаем серверный диск от временного мусора
    Попытка
        УдалитьФайлы(ИмяФайлаНаСервере);
    Исключение
        ЗаписьЖурналаРегистрации("ВыгрузкаDBF.ОшибкаУдаления", 
            УровеньЖурналаРегистрации.Предупреждение, , , 
            ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
    
    Возврат АдресХранилища;
    
КонецФункции

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


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

Решение 2. Оптимальный вариант для конфигурации ЗУП 8.3 (с использованием БСП)

Поскольку в конфигурации «1С:Зарплата и Управление Персоналом» гарантированно встроена Библиотека Стандартных Подсистем (БСП), мы можем существенно упростить клиентский код. Разработчики БСП создали удобные обертки, которые берут на себя всю рутину по обработке асинхронных вызовов в любых типах клиентов (включая веб-клиент в браузере).

Для реализации этого метода серверная функция СформироватьDBFНаСервере() остается без изменений, а клиентская процедура переписывается с использованием модуля ФайловаяСистемаКлиент:


&НаКлиенте
Процедура ВыгрузитьБСП(Команда)
    
    // Шаг 1. Формируем временный файл на сервере и получаем его адрес
    АдресХранилища = СформироватьDBFНаСервере();
    
    Если Не ЗначениеЗаполнено(АдресХранилища) Тогда
        Возврат;
    КонецЕсли;
    
    // Шаг 2. Настраиваем параметры сохранения файла средствами БСП
    ПараметрыСохранения = ФайловаяСистемаКлиент.ПараметрыСохраненияФайла();
    ПараметрыСохранения.Диалог.Фильтр = "Файлы DBF (*.dbf)|*.dbf";
    ПараметрыСохранения.Диалог.Заголовок = "Укажите каталог для сохранения выгрузки";
    
    // Шаг 3. Описываем процедуру обратного вызова после завершения скачивания
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеСохраненияФайла", ЭтотОбъект);
    
    // Шаг 4. БСП самостоятельно откроет диалог и перенесет двоичные данные на диск клиента
    ФайловаяСистемаКлиент.СохранитьФайл(ОписаниеОповещения, АдресХранилища, "export_data.dbf", ПараметрыСохранения);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеСохраненияФайла(ПолученныеФайлы, ДополнительныеПараметры) Экспорт
    
    Если ПолученныеФайлы <> Неопределено И ПолученныеФайлы.Количество() > 0 Тогда
        ПоказатьОповещениеПользователя("Успешно!", , "Файл выгрузки успешно сохранен на ваш диск.");
    КонецЕсли;
    
КонецПроцедуры

Преимущества использования БСП в ЗУП 8.3

Использование механизмов БСП для работы с файлами дает программисту ряд неоспоримых преимуществ:

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

← На главную