Как выгрузить присоединенные файлы большого объема из хранилища 1С и загрузить их в тома на диске базы-приемника?

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

Перенос присоединенных файлов (сертификатов, паспортов качества, сканов документов) между базами 1С часто превращается в сложную задачу, если суммарный объем данных составляет десятки гигабайт. Попытка выгрузить 30 ГБ двоичных данных через типовой обмен Конвертация данных 2.0 (КД2) или механизмы XML-сериализации обычно завершается ошибкой нехватки памяти Out of Memory на сервере приложений. Передача файла через ХранилищеЗначения в XML кодирует бинарный поток в формат Base64, что увеличивает объем передаваемого текста минимум на 33%. В результате рабочий процесс rphost падает, а адреса во временном хранилище теряют актуальность.

В этой статье мы разберем оптимальную технологию переноса двоичных данных из базы-источника (например, УПП 1.3) в базу-приемник (например, ERP 2.5) с сохранением файлов в физические тома на диске, минуя падения по таймаутам и проблемы с памятью.

Почему не стоит использовать COM-соединение

Первая идея, которая часто возникает при переносе — вызывать методы источника из приемника через COMОбъект. Однако проанализируем риски такого подхода на больших объемах:

  1. Нестабильность соединения: При последовательной передаче больших BLOB-объектов через COM-интерфейс сессия часто отваливается по таймауту записи/чтения.
  2. Блокировка ресурсов: Длительный процесс выборки бинарных данных через COM может зависнуть и повлечь за собой сбой всего кластера серверов 1С.
  3. Ограничения разрядности и платформы: COM-соединение устарело и имеет низкую отказоустойчивость при обработке массовых потоковых данных.

Архитектура решения: двухэтапный перенос через промежуточный каталог

Наиболее надежный подход заключается в разделении переноса на два независимых шага:

  1. Выгрузка из источника: Внешняя обработка на стороне базы-источника поочередно считывает двоичные данные из хранилища, записывает их в файлы на жесткий диск и формирует манифест (файл реестра в формате JSON или XML) со сведениями о владельцах файлов (GUID серий, наименования, расширения, даты).
  2. Загрузка в приемник: Обработка в базе-приемнике читает файл манифеста, находит целевые объекты по уникальным идентификаторам и регистрирует файлы в томах хранения с помощью стандартных механизмов БСП.

Шаг 1. Получение и выгрузка данных из базы-источника

Рассмотрим пример запроса для получения файлов, привязанных к сериям номенклатуры в базе УПП 1.3 из справочника ХранилищеДополнительнойИнформации:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Хранилище.Ссылка КАК СсылкаНаХранилище,
    |	Хранилище.Объект КАК Владелец,
    |	Хранилище.Наименование КАК Наименование,
    |	Хранилище.ВидДанных КАК ВидДанных
    |ИЗ
    |	Справочник.ХранилищеДополнительнойИнформации КАК Хранилище
    |ГДЕ
    |	Хранилище.Объект <> НЕОПРЕДЕЛЕНО
    |	И НЕ ВЫРАЗИТЬ(Хранилище.Объект КАК Справочник.СерииНоменклатуры) ЕСТЬ NULL
    |	И НЕ Хранилище.ПометкаУдаления
    |	И Хранилище.ВидДанных = ЗНАЧЕНИЕ(Перечисление.ВидыДополнительнойИнформацииОбъектов.Файл)";

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

КонецЦикла;

Важно для предотвращения утечек памяти: Внутри цикла выборки обязательно сбрасывайте переменные, содержащие ДвоичныеДанные, присваивая им значение Неопределено. Это позволит сборщику мусора платформы своевременно освобождать RAM сервера 1С.

Шаг 2. Загрузка файлов в тома базы-приемника

На стороне базы-приемника (например, ERP) для сохранения файлов в тома диска используем служебные процедуры библиотеки стандартных подсистем (БСП). Основная процедура для работы с томами — РаботаСФайламиСлужебный.ДобавитьФайлВТом().

Проанализируем пример кода загрузки файла из промежуточного каталога в том хранения:


// Инициализируем двоичные данные из сохраненного файла
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлуНаДиске);

// Вызываем стандартный метод БСП для добавления файла в диск
СведенияОФайле = РаботаСФайламиСлужебный.ДобавитьФайлВТом(
    ДвоичныеДанныеФайла,
    ДатаМодификацииУниверсальная,
    НаименованиеФайла,
    РасширениеФайла,
    "", // Описание
    Ложь, // ПроверятьЗапрещенныеРасширения
    НачалоГода(ДатаМодификацииУниверсальная) // Поддиректория тома
);

Как избежать дублирования файлов

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

  1. Расчет хэш-суммы: Перед записью файла рассчитайте его контрольную сумму с помощью объекта платформы ХешированиеДанных (алгоритм MD5 или SHA256).
  2. Проверка по реквизиту: В справочниках присоединенных файлов БСП присутствует реквизит ХэшСумма и Размер. Запросом в приемнике проверьте наличие записи с аналогичной хэш-суммой и размером.
  3. Связка с владельцем: Проверяйте существование присоединенного файла для конкретного владельца (серии номенклатуры) по комбинации параметров: ВладелецФайла + Наименование + Размер. Если файл уже зарегистрирован, повторный вызов сохранения пропускается.

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

← На главную