Вставка BLOB в таблицы ORACLE средствами 1С 8.х с использованием Microsoft OLEDB Provider

Столкнулся с необходимостью выгружать картинки из 1С 8 в ORACLE-таблицу.

Столкнулся с необходимостью выгружать картинки из 1С 8 в ORACLE-таблицу.

Информация в интернетах по этому поводу сводится к тому, что Microsoft OLEDB Provider шибко убогий, используй OracleOLEDB провайдер и будет тебе Щастье.

Я с этим фактом мириться не хотел ровно по той причине, что платформа 1С 8.3, при использовании объекта Внешние Источники Данных, использует именно Microsoft OLEDB Provider и BLOB-ы при этом спокойно вставляются.

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

//Создаем обычный 1С запрос, поля называем, как они называются в таблице ORACLE.
//!!! Поля с BLOB располагаем последними !!!

Если РезультатЗапроса.Пустой() Тогда
Возврат;
КонецЕсли;

Соединение = Новый COMОбъект("ADODB.Connection");
Команда = Новый COMОбъект("ADODB.Command");
СтрокаСоединения = "Driver={Oracle in OraClient11g_home1};Dbq=<DB_NAME>;Uid=<USER_NAME>;Pwd=<PASSWORD>";

Попытка
Соединение.Open(СтрокаСоединения);
Команда.ActiveConnection = Соединение;
Соединение.CommandTimeout = 0;
Статус = Соединение.State;
Параметры = Команда.Parameters;
Исключение
#Если Клиент Тогда
Сообщить(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
#КонецЕсли
Возврат;
КонецПопытки;

Если ОчищатьТаблицу Тогда
Команда.CommandText =
"Delete From " + ИмяТаблицыOracle;
Команда.Execute();
КонецЕсли;

Команда.CommandText =
"INSERT INTO " + ИмяТаблицыOracle + " (BLOB_Name, BLOB_DATA) VALUES(?,?)";

Параметр = Команда.CreateParameter("BLOB_NAME", 200, 1, 1000);
Параметры.Append(Параметр);

ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
Поток = Новый COMОбъект("ADODB.Stream");
Поток.Open();

Пока Выборка.Следующий() Цикл
Параметры.Item("BLOB_Name").Value = Выборка.BLOB_NAME;
Если Выборка.BLOB_DATA <> NULL Тогда
Значение = Выборка.BLOB_DATA.Получить();
Если ТипЗнч(Значение) = Тип("Картинка") Тогда
Значение = Значение.ПолучитьДвоичныеДанные();
КонецЕсли;
РазмерБайт = Значение.Размер();
Значение.Записать(ИмяВременногоФайла);
Поток.LoadFromFile(ИмяВременногоФайла);
Значение = Поток.ReadText();
Иначе
Значение = "";
РазмерБайт = 1;
КонецЕсли;
Если Параметры.Count > 0 Тогда
Для Сч = -(Параметры.Count - 1) По 0 Цикл
Если Параметры.Item(-Сч).Name = "BLOB_DATA" Тогда
Параметры.Delete(-Сч);
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Параметр = Команда.CreateParameter("BLOB_DATA", 205, 1, РазмерБайт);
Параметры.Append(Параметр);
Параметры.Item("BLOB_DATA").AppendChunk(Значение);
Попытка
Команда.Execute();
Исключение
#Если Клиент Тогда
Сообщить(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
#КонецЕсли
КонецПопытки;
КонецЦикла;

УдалитьФайлы(ИмяВременнногоФайла);
Соединение.Close();

При создании этого решения хотелось бы отдельное "спасибо" сказать разработчикам платформы 1С. Все действия выполнялись на версии платформы 8.3.14.1779

Если сделать:

ДвоичныеДанные.Записать(ИмяВременногоФайла);
Поток = Новый ЧтениеТекста(ИмяВременногоФайла, КодировкаТекста.UTF16);
Значение = Поток.Прочитать();

то Значение будет содержать строку, которая отличается от той, что выдает ADODB.Stream и она даже не "влазит" в Параметры.Item(Колонка.Имя).AppendChunk(Значение) — появляется сообщенио о том, что используется не правильный символ.

 

Если сделать:

ЧтениеДанных = Новый ЧтениеДанных(ДвоичныеДанные, КодировкаТекста.UTF16);
Значение = ЧтениеДанных.ПрочитатьСимволы();

то Значение будет содержать строку, которая отличается и от той, что выдает ADODB.Stream, и от той, что выдает ЧтениеТекста. Значение при этом без проблем залазит в Параметры.Item(Колонка.Имя).AppendChunk(Значение), но в итоге картинка из него не собирается вообще, а представляется из себя просто набор байт.

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *