Перенос присоединенных файлов (сертификатов, паспортов качества, сканов документов) между базами 1С часто превращается в сложную задачу, если суммарный объем данных составляет десятки гигабайт. Попытка выгрузить 30 ГБ двоичных данных через типовой обмен Конвертация данных 2.0 (КД2) или механизмы XML-сериализации обычно завершается ошибкой нехватки памяти Out of Memory на сервере приложений. Передача файла через ХранилищеЗначения в XML кодирует бинарный поток в формат Base64, что увеличивает объем передаваемого текста минимум на 33%. В результате рабочий процесс rphost падает, а адреса во временном хранилище теряют актуальность.
В этой статье мы разберем оптимальную технологию переноса двоичных данных из базы-источника (например, УПП 1.3) в базу-приемник (например, ERP 2.5) с сохранением файлов в физические тома на диске, минуя падения по таймаутам и проблемы с памятью.
Первая идея, которая часто возникает при переносе — вызывать методы источника из приемника через COMОбъект. Однако проанализируем риски такого подхода на больших объемах:
Наиболее надежный подход заключается в разделении переноса на два независимых шага:
Рассмотрим пример запроса для получения файлов, привязанных к сериям номенклатуры в базе УПП 1.3 из справочника ХранилищеДополнительнойИнформации:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Хранилище.Ссылка КАК СсылкаНаХранилище,
| Хранилище.Объект КАК Владелец,
| Хранилище.Наименование КАК Наименование,
| Хранилище.ВидДанных КАК ВидДанных
|ИЗ
| Справочник.ХранилищеДополнительнойИнформации КАК Хранилище
|ГДЕ
| Хранилище.Объект <> НЕОПРЕДЕЛЕНО
| И НЕ ВЫРАЗИТЬ(Хранилище.Объект КАК Справочник.СерииНоменклатуры) ЕСТЬ NULL
| И НЕ Хранилище.ПометкаУдаления
| И Хранилище.ВидДанных = ЗНАЧЕНИЕ(Перечисление.ВидыДополнительнойИнформацииОбъектов.Файл)";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Получаем двоичные данные из хранилища значения
ДанныеХранилища = Выборка.СсылкаНаХранилище.Хранилище.Получить();
Если ТипЗнч(ДанныеХранилища) = Тип("ДвоичныеДанные") Тогда
// Формируем имя файла на диске на основе УИД объекта
УИДСтрокой = Строка(Выборка.СсылкаНаХранилище.УникальныйИдентификатор());
ИмяФайлаНаДиске = КаталогВыгрузки + УИДСтрокой + ".bin";
// Записываем файл на диск
ДанныеХранилища.Записать(ИмяФайлаНаДиске);
// Освобождаем оперативную память
ДанныеХранилища = Неопределено;
КонецЕсли;
КонецЦикла;
Важно для предотвращения утечек памяти: Внутри цикла выборки обязательно сбрасывайте переменные, содержащие ДвоичныеДанные, присваивая им значение Неопределено. Это позволит сборщику мусора платформы своевременно освобождать RAM сервера 1С.
На стороне базы-приемника (например, ERP) для сохранения файлов в тома диска используем служебные процедуры библиотеки стандартных подсистем (БСП). Основная процедура для работы с томами — РаботаСФайламиСлужебный.ДобавитьФайлВТом().
Проанализируем пример кода загрузки файла из промежуточного каталога в том хранения:
// Инициализируем двоичные данные из сохраненного файла
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлуНаДиске);
// Вызываем стандартный метод БСП для добавления файла в диск
СведенияОФайле = РаботаСФайламиСлужебный.ДобавитьФайлВТом(
ДвоичныеДанныеФайла,
ДатаМодификацииУниверсальная,
НаименованиеФайла,
РасширениеФайла,
"", // Описание
Ложь, // ПроверятьЗапрещенныеРасширения
НачалоГода(ДатаМодификацииУниверсальная) // Поддиректория тома
);
При повторных запусках обработки или переносе пересекающихся данных необходимо защитить базу от дублей. Выясним, как проверить наличие файла перед его созданием:
ХешированиеДанных (алгоритм MD5 или SHA256).ХэшСумма и Размер. Запросом в приемнике проверьте наличие записи с аналогичной хэш-суммой и размером.ВладелецФайла + Наименование + Размер. Если файл уже зарегистрирован, повторный вызов сохранения пропускается.Применение такой схемы позволяет перенести файлы любого объема (даже сотни гигабайт) без нагрузки на оперативную память, гарантирует устойчивость к обрывам связи и сохраняет полную целостность данных при интеграции.