В процессе интеграции 1С со сторонними системами часто возникает задача переноса бинарных данных, таких как сканы документов, изображения или PDF-файлы, которые хранятся непосредственно в таблицах MS SQL Server в полях типа Image или Varbinary(max). Поскольку прямой перенос между базами может быть затруднен из-за различий в структурах, наиболее надежным способом является промежуточная выгрузка данных в файловую систему. Рассмотрим подробнее, как реализовать этот процесс, проанализируем различные подходы и разберем конкретные примеры кода.
Это классический метод, который позволяет программно подключиться к базе данных SQL напрямую из кода 1С, выполнить запрос и сохранить результат в файл. Этот способ особенно полезен, когда у нас нет возможности или желания добавлять таблицы во «Внешние источники данных» 1С.
Давайте разберем алгоритм работы по шагам. Сначала мы создаем соединение с сервером, затем получаем набор записей (RecordSet), и, наконец, используем специальный объект ADODB.Stream для записи бинарного потока в файл на диске. Проанализируем пример кода:
// Настройка параметров подключения
СерверSQL = "SQL-SERVER-NAME";
БазаДанныхSQL = "TargetDB";
ПользовательSQL = "sa";
ПарольSQL = "YourStrongPassword";
// Создаем COM-объект для соединения
Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.ConnectionTimeout = 30;
СтрокаПровайдера = "Provider=SQLOLEDB;Data Source=" + СерверSQL + ";Initial Catalog=" + БазаДанныхSQL + ";User ID=" + ПользовательSQL + ";Password=" + ПарольSQL + ";";
Попытка
Соединение.Open(СтрокаПровайдера);
Исключение
Сообщить("Ошибка подключения: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Запрос для получения BLOB-данных
ТекстЗапроса = "SELECT ID, FileName, BinaryContent FROM DocumentsTable WHERE ID = 101";
RecordSet = Соединение.Execute(ТекстЗапроса);
Если НЕ RecordSet.EOF Тогда
// Создаем поток для работы с бинарными данными
ADOStream = Новый COMОбъект("ADODB.Stream");
ADOStream.Type = 1; // 1 - Binary
ADOStream.Open();
// Записываем значение поля в поток
ADOStream.Write(RecordSet.Fields("BinaryContent").Value);
// Сохраняем поток в файл на диске
ИмяФайла = "C:\Temp\" + RecordSet.Fields("FileName").Value;
ADOStream.SaveToFile(ИмяФайла, 2); // 2 - перезаписывать файл, если существует
ADOStream.Close();
КонецЕсли;
RecordSet.Close();
Соединение.Close();
Важный нюанс: при использовании этого метода на 64-битных серверах 1С необходимо убедиться, что в системе установлены соответствующие 64-битные драйверы OLE DB (например, MSOLEDBSQL). В противном случае COM-объект не сможет инициализироваться.
Начиная с версии платформы 8.3, работа с внешними базами данных стала значительно проще. Если мы подключим таблицу SQL через механизм «Внешние источники данных», платформа 1С автоматически сопоставит типы данных. Поля Image и Varbinary будут представлены в 1С как объект типа ДвоичныеДанные.
Рассмотрим, как в этом случае выглядит процесс выгрузки. Нам не нужно заботиться о COM-объектах и потоках ADO, достаточно использовать встроенные методы платформы:
Записать() объекта ДвоичныеДанные.
// Пример получения данных через внешний источник
Выборка = ВнешниеИсточникиДанных.МояБазаSQL.Таблицы.DocumentsTable.Выбрать();
Пока Выборка.Следующий() Цикл
// Поле BinaryContent автоматически типизируется как ДвоичныеДанные
БинарныеДанные = Выборка.BinaryContent;
Если ТипЗнч(БинарныеДанные) = Тип("ДвоичныеДанные") Тогда
ПутьКФайлу = "D:\Export\" + Выборка.ID + ".pdf";
БинарныеДанные.Записать(ПутьКФайлу);
КонецЕсли;
КонецЦикла;
Этот метод является наиболее предпочтительным для современной разработки, так как он типизирован, безопасен и не зависит от внешних библиотек (DLL), зарегистрированных в операционной системе.
Часто сторонние программы (и сама 1С при хранении файлов в информационной базе) сохраняют данные в сжатом виде (например, используя алгоритм GZIP). Если мы просто выгрузим такие данные в файл, он окажется «битым» и не откроется стандартными средствами.
В современных версиях MS SQL Server (2016 и выше) существует встроенная функция DECOMPRESS. Если мы выяснили, что данные в базе хранятся в сжатом виде, наш запрос должен выглядеть следующим образом:
// Пример запроса с распаковкой данных на стороне SQL Server
ТекстЗапроса = "SELECT FileName, CAST(DECOMPRESS(BinaryContent) AS VARBINARY(MAX)) as UnpackedData FROM DocumentsTable";
Если же версия SQL Server старая, распаковку придется выполнять на стороне 1С. Для этого можно использовать объект ЧтениеZipФайла или специализированные библиотеки, если данные сжаты алгоритмом, отличным от стандартного ZIP/GZIP.
Если стоит задача разовой выгрузки огромного массива данных (сотни тысяч файлов), использование 1С или COM-объектов может быть медленным. В таких случаях мы можем воспользоваться утилитой командной строки BCP (Bulk Copy Program).
Проанализируем пример команды для выгрузки одного файла:
bcp "SELECT BinaryContent FROM MyDatabase.dbo.DocumentsTable WHERE ID=1" queryout "C:\Temp\document.pdf" -T -n
Здесь флаг -n означает использование нативных типов данных SQL, а -T — использование доверительного соединения (Windows Authentication). Для массовой выгрузки обычно создается скрипт (например, на языке T-SQL), который генерирует список команд для каждого файла и выполняет их через xp_cmdshell.
Подводя итог, выделим основные критерии выбора решения:
Таким образом, мы рассмотрели основные инструменты для работы с BLOB-данными. Выбор конкретного метода зависит от архитектуры вашего решения и требований к производительности.