14 мар. 2022 г.

Отправить файл POST запросом с учетом ultipart/form-data

Пример запроса отправки прайс листа на сервис "Вачсно" с последующей обработкой ответа от сервиса

#Область ВЧАСНО
Функция ОтправитьФайлПрайсВчасно(ПолноеИмяФайла, МассивID)
//пример запроса:
//
//POST https://edi.vchasno.ua/api/documents/prices?buyer_edrpou=ИдентификаторКонтрагентаДляКоторогоВыгружаемПрайс
//
//authorization: <vchasno-edi_token>
//content-type: multipart/form-data; boundary=BOUNDARY
//
//--BOUNDARY
//Content-Disposition: form-data; name="file"; filename="pricat.xml"
//Content-Type: application/xml
//<?xml version='1.0' encoding='utf-8'?>
//<PRICAT>
//...
//</PRICAT>
//--BOUNDARY--
урлОтправитьДокумент = "/api/documents/prices?buyer_edrpou=" + "ИдентификаторКонтрагентаДляКоторогоВыгружаетсяПрайс";
СерверАПИ = "edi.vchasno.ua";
Токен = "ХХХХХХХХХХХХХХХХ";
BOUNDARY = Строка(Новый УникальныйИдентификатор); //просто произвольные символы
лПолноеИмяФайлаXML = ПолноеИмяФайла; //ХМЛ файл, с которого будем получать ХМЛ строку
тФайл = Новый Файл(лПолноеИмяФайлаXML);
Если НЕ тФайл.Существует() Тогда
Сообщить(НСтр("ru = 'Не найден файл '; uk = 'Не знайдено файл '")+лПолноеИмяФайлаXML+" для отправки на сервис ""Вчасно""", СтатусСообщения.Внимание);
Возврат МассивID;
ИначеЕсли НЕ тФайл.ЭтоФайл() Тогда
Сообщить(НСтр("ru = 'Не является файлом '; uk = 'Не є файлом '")+лПолноеИмяФайлаXML+" для отправки на сервис ""Вчасно""", СтатусСообщения.Внимание);
Возврат МассивID;
КонецЕсли;
Текст = Новый ТекстовыйДокумент;
тмпОтвет = ПолучитьИмяВременногоФайла("txt");
ИмяФайлаОтправки = ПолучитьИмяВременногоФайла("txt");
ФайлОтправки = Новый ЗаписьТекста(ИмяФайлаОтправки, КодировкаТекста.ANSI, Символы.ПС, Ложь);
ФайлОтправки.ЗаписатьСтроку("--" + Boundary);
ФайлОтправки.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""pricat.xml""");
ФайлОтправки.ЗаписатьСтроку("Content-Type: application/xml");
ФайлОтправки.ЗаписатьСтроку("");
//вставка Прайса ХМЛ
ТекстXML = Новый ТекстовыйДокумент;
ТекстXML.Прочитать(лПолноеИмяФайлаXML, КодировкаТекста.ANSI, );
ФайлОтправки.ЗаписатьСтроку(СокрЛП(ТекстXML.ПолучитьТекст()));
ФайлОтправки.ЗаписатьСтроку("");
ФайлОтправки.ЗаписатьСтроку("--" + Boundary + "--");
ФайлОтправки.Закрыть();
ЗаголовокHTTP = Новый Соответствие();
ЗаголовокHTTP.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);
ЗаголовокHTTP.Вставить("Authorization", Токен);
ХСоединение = Новый HTTPСоединение( СерверАПИ,,,,, 60, Новый ЗащищенноеСоединениеOpenSSL());
ХЗапрос = Новый HTTPЗапрос(урлОтправитьДокумент, ЗаголовокHTTP);
ХЗапрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
ХОтвет = ХСоединение.ОтправитьДляОбработки(ХЗапрос, тмпОтвет);
КодОтвета = ХОтвет.КодСостояния;
Если КодОтвета = 200 Тогда
Попытка
УдалитьФайлы(лПолноеИмяФайлаXML);
Исключение
Сообщить(НСтр("ru = 'Неудачная попытка удаления файла '; uk = 'Невдала спроба видалення файла '")+лПолноеИмяФайлаXML, СтатусСообщения.Внимание);
Сообщить(ОписаниеОшибки(), СтатусСообщения.Внимание);
КонецПопытки;
Если ВРЕГ(ХОтвет.Заголовки.Получить("Content-Type")) = ВРЕГ("application/json") Тогда
тФайлОтвета = Новый Файл(тмпОтвет);
Текст.Прочитать(тмпОтвет, КодировкаТекста.UTF8);
ЧтениеДЖ = Новый ЧтениеJSON;
ЧтениеДЖ.УстановитьСтроку(Текст.ПолучитьТекст());
ОбъектДЖ = ПрочитатьJSON(ЧтениеДЖ, Истина); // читаем в соответвие
ИДВчасно = ОбъектДЖ.Получить("id");
Если ИДВчасно <> Неопределено Тогда
Сообщить("Отправленный прас получил ИД: " + ИДВчасно);
МассивID.Добавить(ИДВчасно);
Попытка
УдалитьФайлы(тмпОтвет);
Исключение
Сообщить(НСтр("ru = 'Неудачная попытка удаления файла '; uk = 'Невдала спроба видалення файла '")+тмпОтвет, СтатусСообщения.Внимание);
Сообщить(ОписаниеОшибки(), СтатусСообщения.Внимание);
КонецПопытки;
Возврат МассивID
КонецЕсли;
Иначе
Возврат МассивID
КонецЕсли;
Иначе
Сообщить(НСтр("ru = 'Получен ответ с кодом '; uk = 'Отримано відповідь з кодом '")+КодОтвета, СтатусСообщения.Внимание);
// разобрать ошибки
ОшибкаРазбора = Ложь;
тФайлОтвета = Новый Файл(тмпОтвет);
Если НЕ тФайлОтвета.Существует() Тогда
Сообщить(НСтр("ru = 'Не найден файл ответа сервиса: '; uk = 'Не знайдено файл відповіді сервісу: '")+тмпОтвет, СтатусСообщения.Внимание);
Иначе
Текст.Прочитать(тмпОтвет, КодировкаТекста.UTF8);
Если Текст.КоличествоСтрок() > 0 Тогда
ОтветСервера = Текст.ПолучитьТекст();
_ЧтениеXML = Новый ЧтениеXML;
Попытка
_ЧтениеXML.УстановитьСтроку(ОтветСервера);
Исключение
Сообщить(НСтр("ru = 'Неудачная попытка чтения ответа сервиса: '; uk = 'Невдала спроба читання відповіді сервісу: '")+ОписаниеОшибки(), СтатусСообщения.Внимание);
ОшибкаРазбора = Истина;
КонецПопытки;
КонецЕсли;
Если НЕ ОшибкаРазбора Тогда
Поз = Найти(Лев(ОтветСервера, 5), "xml");
Если Поз = 0 Тогда
Сообщить(НСтр("ru = 'Неудачная попытка разбора ответа сервиса (Код состояния = '; uk = 'Невдала спроба розбору відповіді сервісу (Код стану = '")+КодОтвета+"): ", СтатусСообщения.Внимание);
Сообщить(ОтветСервера, СтатусСообщения.Внимание);
Иначе
ОбработатьОписаниеОшибки(_ЧтениеXML, КодОтвета);
КонецЕсли;
КонецЕсли;
Возврат МассивID
КонецЕсли;
КонецЕсли;
Возврат МассивID
КонецФункции
Процедура ОбработатьОписаниеОшибки(_ЧтениеXML, КодСостояния)
Если КодСостояния = 504 Тогда // иная структура ответа
Сообщить(НСтр("ru = 'Ответ сервиса (Код состояния = '; uk = 'Відповідь сервісу (Код стану = '")+КодСостояния+")", СтатусСообщения.Внимание);
Возврат;
КонецЕсли;
СтруктураОшибки = Новый Структура("title, body");
ИмяУзла = "";
Читать = Ложь;
Пока _ЧтениеXML.Прочитать() Цикл
ТипУзла = _ЧтениеXML.ТипУзла;
Если ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Если ИмяУзла = "files" Тогда
СтруктураОшибки.Вставить("ИмяФайла", _ЧтениеXML.Имя);
Читать = Ложь;
Иначе
ИмяУзла = _ЧтениеXML.Имя;
Читать = СтруктураОшибки.Свойство(ИмяУзла);
КонецЕсли;
ИначеЕсли ТипУзла = ТипУзлаXML.Текст И Читать Тогда
СтруктураОшибки.Вставить(ИмяУзла, _ЧтениеXML.Значение);
Читать = Ложь;
Иначе
Читать = Ложь;
КонецЕсли;
КонецЦикла;
Сообщить(НСтр("ru = 'Ответ сервиса (Код состояния = '; uk = 'Відповідь сервісу (Код стану = '")+КодСостояния+"):", СтатусСообщения.Внимание);
Сообщить(" - заголовок: "+СтруктураОшибки["title"], СтатусСообщения.Внимание);
Сообщить(" - описание: "+СтруктураОшибки["body"] , СтатусСообщения.Внимание);
КонецПроцедуры

#КонецОбласти

7 февр. 2021 г.

Переносим логику выполнения кода в модуль внешней обработки

 Бывает затруднено динамическое обновление клиентской базы, поэтому часто програмный код, который "не устойчив" пишу на стороне модуля внешней обработки, который потом вызываю в нужном для себе месте. 

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

В результате выходт, как бы "онлайн" изменения логики без нужды обновление конфигурации.

Пример вызова процедуры из параметрами, которая находиться в модуле внешней обработки 

с именем "[ИС] Внешние процедуры и функции".

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

Общий модуль "исОбщегоНазначения" можно посмотреть в этой публикации

Открыть внешнюю обработку из обработки

Нужно, при открытии формы обработки чтобы текущая открытая форма обработки закрывалась и сразу же открывалась внешняя форма обработки.

Такая реализация нужно для быстрого внесения изменений в логику внешней обработки не обновляя конфигурацию.

Модуль формы

Процедура КнопкаВыполнитьНажатие(Кнопка)
    // Вставить содержимое обработчика.
КонецПроцедуры

Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    
    Попытка
        //запуск процедуры в обработке  
        исОбщегоНазначения.ОткрытьФормуВнешнейОбработки("[ИС] Обмен с АЗС");
        
        //удалим внешнюю временную обработку        
        УдалитьФайлы(ОбработкаОбъект.ИспользуемоеИмяФайла); 
    Исключение
    КонецПопытки;
    
    Отказ = Истина; //закроем текущую форму
    
КонецПроцедуры

Модуль общего модуля который называется исОбщегоНазначения

#Область РаботаСЗапускомВнешнихОтчетовИОбработок

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

КонецФункции

//Выполняет имя экспортной процедуры из обработка объект
//СтруктураПараметров = Структура параметров которые нужно передать и обработать на стороне обработки
Процедура ВыполнитьПроцедуруОбработки(ОбработкаОбъет, ИмяПроцедуры, СтруктураПараметров = "") Экспорт 
    
    Если ПустаяСтрока(ИмяПроцедуры) Тогда 
        Возврат 
    КонецЕсли;  
    
    Если ОбработкаОбъет = Неопределено Тогда 
        Возврат 
    КонецЕсли;
    
    Попытка
        Если ЗначениеЗаполнено(СтруктураПараметров) Тогда 
            Выполнить("ОбработкаОбъет."+ИмяПроцедуры+"(СтруктураПараметров)")
        Иначе 
            Выполнить("ОбработкаОбъет."+ИмяПроцедуры+"()")
        КонецЕсли;
    Исключение
        Сообщить(ОписаниеОшибки())
    КонецПопытки;
        
КонецПроцедуры

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

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

#КонецОбласти

Пример использования выше процедур при быстром обновлении логики програмы.

Найти объект в базе по УИД

 Один из способов найти по УИДу объект в базе

Функция ПолучитьОбъектПоУИД(УИДОбъекта)  

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

Программно добавить кнопки на форму

 Есть форма (УФ) на которой размещено две группы 

"Справочники", "Документы"

нужно вывести все справочники и документы из конфигурации в виде кнопок на эту форму в подходящую группу

Результат должен быть таким


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Для Каждого текСправочник Из Метаданные.Справочники Цикл 
        
        НоваяКоманда = Команды.Добавить("Команда_"+текСправочник.Имя);
        НоваяКоманда.Действие = "Действие_"+текСправочник.Имя;//Имя процедуры
        НоваяКоманда.Заголовок = текСправочник.Представление();
        
        НовыйЭлемент = Элементы.Добавить("Элемент_"+текСправочник.Имя, Тип("КнопкаФормы"), Элементы.НСИ);
        НовыйЭлемент.ИмяКоманды = "Команда_"+текСправочник.Имя;
        НовыйЭлемент.Картинка = БиблиотекаКартинок.Справочник;
        НовыйЭлемент.Отображение = ОтображениеКнопки.КартинкаИТекст; 
        
    КонецЦикла;
    
    Для Каждого текДокумент Из Метаданные.Документы Цикл 
        
        НоваяКоманда = Команды.Добавить("Команда_"+текДокумент.Имя);
        НоваяКоманда.Действие = "Действие_"+текДокумент.Имя;//Имя процедуры
        НоваяКоманда.Заголовок = текДокумент.Представление();
        
        НовыйЭлемент = Элементы.Добавить("Элемент_"+текДокумент.Имя, Тип("КнопкаФормы"), Элементы.Документы);
        НовыйЭлемент.ИмяКоманды = "Команда_"+текДокумент.Имя;
        НовыйЭлемент.Картинка = БиблиотекаКартинок.Документ;
        НовыйЭлемент.Отображение = ОтображениеКнопки.КартинкаИТекст;
        
    КонецЦикла;
    
КонецПроцедуры

Соответственно, нужно в ручном режиме добавить процедуры нажатия по примеру

&НаКлиенте
Процедура Действие_Контрагенты(Команда)
    
    ОткрытьФорму("Справочник.Контрагенты.ФормаСписка");
    
КонецПроцедуры

&НаКлиенте
Процедура Действие_Номенклатура(Команда)
    
    ОткрытьФорму("Справочник.Номенклатура.ФормаСписка");
    
КонецПроцедуры


 

CopyPaste Copyright © 2017 - |- Шаблон создан O Pregador - |- Отредактирован myr4ik07