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

Тема в разделе "Обмен данными в "1С:Предприятие 8"", создана пользователем nomad_irk, 8 авг 2019.

  1. TopicStarter Overlay
    nomad_irk
    Online

    nomad_irk Гуру в 1С

    Регистрация:
    20 окт 2008
    Сообщения:
    9.858
    Симпатии:
    1.025
    Баллы:
    204
    Столкнулся с необходимостью выгружать картинки из 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(Значение), но в итоге картинка из него не собирается вообще, а представляется из себя просто набор байт.
    Последнее редактирование: 8 авг 2019
    Yuriy_Alexandrovich нравится это.