Имя: Пароль:
1C
1С v8
Отправка картинки в Телеграм
0 телега
 
11.11.20
11:43
Отправляю картинку с помощью вот этого кода:
        Токен = текПараметрыСеанса.Токен;
        СерверTg = текПараметрыСеанса.Сервер;
        
        ИмяФайла = ПолучитьИмяВременногоФайла("jpg");
        
        мТекущееОсновноеИзображение.Записать(ИмяФайла);
        
        ФайлСФото = Новый Файл(ИмяФайла);
        
        СтрокаСоединения = "bot" + Токен + "/sendPhoto?chat_id=" + СтрЗаменить(Формат(chat_id, "ЧДЦ=0; ЧС=; ЧРГ=.; ЧГ=0"), ".", "") + "photo=";
        
        Boundary = "----"+Строка(Новый УникальныйИдентификатор());
        
        //Определяем массив для процедуры ОбъединитьФайлы
        МассивФайловДляОбъединения = Новый Массив;
        
        //Формируем начальный фрагмент файла POST-запроса
        ИмяФайлаОтправкиНачало = ПолучитьИмяВременногоФайла("txt");
        ФайлОтправкиНачало = Новый ЗаписьТекста(ИмяФайлаОтправкиНачало, КодировкаТекста.UTF8);
        
        //Формируем конечный фрагмент файла POST-запроса
        ИмяФайлаОтправкиКонец = ПолучитьИмяВременногоФайла("txt");
        ФайлаОтправкиКонец = Новый ЗаписьТекста(ИмяФайлаОтправкиКонец, КодировкаТекста.UTF8);
        
        ТекстДляОтправки = "";
        
        ТекстДляОтправки = ТекстДляОтправки + Boundary + Символы.ПС;
        ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""photo""; filename=/""" + ИмяФайла + """" + Символы.ПС;
        ТекстДляОтправки = ТекстДляОтправки + "Content-Type: image/jpeg";
        
        ФайлОтправкиНачало.ЗаписатьСтроку(ТекстДляОтправки );
        ФайлОтправкиНачало.Закрыть();
        
        МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиНачало);
        
        МассивФайловДляОбъединения.Добавить(СокрЛП(ИмяФайла));
        
        ТекстДляОтправки = "" + Символы.ПС;
        ТекстДляОтправки = ТекстДляОтправки + Boundary;
        
        ФайлаОтправкиКонец.ЗаписатьСтроку(ТекстДляОтправки);
        ФайлаОтправкиКонец.Закрыть();
        МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиКонец);
        
        ИмяФайлаОтправки = ПолучитьИмяВременногоФайла("txt");
        ОбъединитьФайлы(МассивФайловДляОбъединения, ИмяФайлаОтправки);
        
        HTTPЗапрос = Новый HTTPЗапрос;
        Заголовки = Новый Соответствие;
        
        HTTPЗапрос.Заголовки.Вставить("Connection", "keep-alive");
        HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary="+Boundary);
        
        HTTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
        HTTPЗапрос.АдресРесурса = СтрокаСоединения;
        
        HTTPСоединение = Новый HTTPСоединение(СерверTg,443,,,,,Новый ЗащищенноеСоединениеOpenSSL());
        
        Попытка
            Ответ = HTTPСоединение.Получить(HTTPЗапрос);
            
            КодСостояния     = Ответ.КодСостояния;
            СтрокаОтвета     = Ответ.ПолучитьТелоКакСтроку();

            
            Если КодСостояния=200 тогда
                ЧтениеОтвета = Новый ЧтениеJSON;
                ЧтениеОтвета.УстановитьСтроку(СтрокаОтвета);
                РезультатСтруктура = ПрочитатьJSON(ЧтениеОтвета);
                Если РезультатСтруктура.ok = Истина Тогда
                    СтруктураMessage = РезультатСтруктура.result;
                КонецЕсли;
            Иначе
                Сообщить("КодСостояния "+КодСостояния);
                Сообщить(СтрокаОтвета);
            КонецЕсли;
        Исключение
            Сообщить(ОписаниеОшибки());
        КонецПопытки;

Однако ответ {"ok":false,"error_code":400,"description":"Bad Request: there is no photo in the request"}
Смотрю состояние файла ИмяФайлаОтправки и вижу что он внутри содержит все необходимые данные:

----1a9121fc-3358-4ff3-9117-f26721d66194
Content-Disposition: form-data; name="photo"; filename="/C:/EVE/111.jpg"
Content-Type: image/jpeg

<тут куча двоичных данных>

----1a9121fc-3358-4ff3-9117-f26721d66194


В Postman сделал отправку, преобразовал в HTTP и вижу:

GET /bot<ТОКЕН>/sendPhoto?chat_id=<ID Чата>&photo= HTTP/1.1
Host: api.telegram.org
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="photo"; filename="/C:/EVE/111.jpg"
Content-Type: image/jpeg

(data)
----WebKitFormBoundary7MA4YWxkTrZu0gW

что в целом совпадает с моими данными. Что же не так?
1 Dzenn
 
гуру
11.11.20
11:49
попробуй убрать строку
Content-Type: image/jpeg

и последня строка должна быть ----WebKitFormBoundary7MA4YWxkTrZu0gW--, а не ----WebKitFormBoundary7MA4YWxkTrZu0gW
2 Dzenn
 
гуру
11.11.20
11:50
ну и плюс, через файлы уже не феншуй, а феншуй через потоки
3 телега
 
11.11.20
11:54
Попробовал, результат тот же. Итоговый файл:
----e11508aa-d3da-4eef-ba31-d02c61b203fc
Content-Disposition: form-data; name="photo"; filename="/<Тут путь к файлу>"

<тут куча двоичных данных>
----e11508aa-d3da-4eef-ba31-d02c61b203fc--

Но почему эти данные есть в сформированном Постманом? Там есть и указание на тип данных и отсутствует "--" в конце, и работает!
4 телега
 
11.11.20
11:57
(2) Нет ли кусочечка образца?
5 телега
 
11.11.20
12:01
Ещё один вопрос: почему в Постмане перед путём стоит "/" и имеет ли значение "/" или "\" в самом пути к файлу ("C:\" или "C:/")? Учитывая что в теле уже содержатся двоичные данные.
6 Dzenn
 
гуру
11.11.20
12:04
(4) на инфостарте есть примеры, так ссылку сразу не найду

плюс, по коду заметил, что другие параметры типа chat_id передаются не через мультипарт, а через строку соединения, что тоже не факт что правильно. у меня в http://catalog.mista.ru/public/627500/ все параметры передаются через мультипарт
7 телега
 
11.11.20
12:05
Я именно с инфостарта и брал образец, даже тупое копирование у меня не заработало, потом я его переделал с оглядкой на отработавший пример HTTP из Постмана.
Сейчас посмотрю, спасибо большое.
8 телега
 
11.11.20
12:27
Увы ни перенос в мультипарт, ни удаление "photo=" из строки соединения ситуацию не изменили.
9 телега
 
11.11.20
12:54
Кстати, кто знает как простым способом проверить HTTP запрос? В Firefox через консоль можно?
10 телега
 
11.11.20
14:06
Заработало. Я не знаю, чёрт возьми как, но заработало.
Это работает:

        Токен = текПараметрыСеанса.Токен;
        СерверTg = текПараметрыСеанса.Сервер;
        
        ИмяФайла = ПолучитьИмяВременногоФайла("jpg");
        
        мТекущееОсновноеИзображение.Записать(ИмяФайла);
        
        ФайлСФото = Новый Файл(ИмяФайла);
        
        СтрокаСоединения = "bot" + Токен + "/sendPhoto";
        
        Boundary = "----"+Строка(Новый УникальныйИдентификатор());
        
        //Определяем массив для процедуры ОбъединитьФайлы
        МассивФайловДляОбъединения = Новый Массив;
        
        //Формируем начальный фрагмент файла POST-запроса
        ИмяФайлаОтправкиНачало = ПолучитьИмяВременногоФайла("txt");
        ФайлОтправкиНачало = Новый ЗаписьТекста(ИмяФайлаОтправкиНачало, КодировкаТекста.UTF8);
        
        //Формируем конечный фрагмент файла POST-запроса
        ИмяФайлаОтправкиКонец = ПолучитьИмяВременногоФайла("txt");
        ФайлаОтправкиКонец = Новый ЗаписьТекста(ИмяФайлаОтправкиКонец, КодировкаТекста.UTF8);
        
        ТекстДляОтправки = "";
        
        ТекстДляОтправки = ТекстДляОтправки + "--" + Boundary + Символы.ПС;
        ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""chat_id""" + Символы.ПС + Символы.ПС + СтрЗаменить(Формат(chat_id, "ЧДЦ=0; ЧС=; ЧРГ=.; ЧГ=0"), ".", "") + Символы.ПС;
        
        ТекстДляОтправки = ТекстДляОтправки + "--" + Boundary + Символы.ПС;
        ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""photo""; filename=""/" + ФайлСФото.Имя + """" + Символы.ПС;
        ТекстДляОтправки = ТекстДляОтправки + "Content-Type: image/jpeg" + Символы.ПС;
        
        ФайлОтправкиНачало.ЗаписатьСтроку(ТекстДляОтправки);
        ФайлОтправкиНачало.Закрыть();
        
        МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиНачало);
        
        МассивФайловДляОбъединения.Добавить(СокрЛП(ИмяФайла));
        
        ТекстДляОтправки = "" + Символы.ПС;
        ТекстДляОтправки = ТекстДляОтправки + "--" +  Boundary+"--";
        
        ФайлаОтправкиКонец.ЗаписатьСтроку(ТекстДляОтправки);
        ФайлаОтправкиКонец.Закрыть();
        МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиКонец);
        
        ИмяФайлаОтправки = ПолучитьИмяВременногоФайла("txt");
        ОбъединитьФайлы(МассивФайловДляОбъединения, ИмяФайлаОтправки);
        
        HTTPЗапрос = Новый HTTPЗапрос;
        Заголовки = Новый Соответствие;
        
        HTTPЗапрос.Заголовки.Вставить("Connection", "keep-alive");
        HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary="+Boundary);
        
        HTTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
        HTTPЗапрос.АдресРесурса = СтрокаСоединения;
        
        HTTPСоединение = Новый HTTPСоединение(СерверTg,443,,,,,Новый ЗащищенноеСоединениеOpenSSL());
        
        Попытка
            Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
            
            КодСостояния     = Ответ.КодСостояния;
            СтрокаОтвета     = Ответ.ПолучитьТелоКакСтроку();

            
            Если КодСостояния=200 тогда
                ЧтениеОтвета = Новый ЧтениеJSON;
                ЧтениеОтвета.УстановитьСтроку(СтрокаОтвета);
                РезультатСтруктура = ПрочитатьJSON(ЧтениеОтвета);
                Если РезультатСтруктура.ok = Истина Тогда
                    СтруктураMessage = РезультатСтруктура.result;
                КонецЕсли;
            Иначе
                Сообщить("КодСостояния "+КодСостояния);
                Сообщить(СтрокаОтвета);
            КонецЕсли;
        Исключение
            Сообщить(ОписаниеОшибки());
        КонецПопытки;
11 Kassern
 
11.11.20
14:47
(10) я могу конечно ошибаться, но скорее всего проблема была именно в строчке  HTTPСоединение.Получить(HTTPЗапрос);
На https ресурсах данный метод может косячить, лучше всего использовать ОтправитьДляОбработки или ВызватьHTTPМетод (что на мой взгляд еше лучше, так как сам указываешь нужный метод, а не 1ска за тебя решает)
12 oleg_km
 
11.11.20
15:58
Так HTTPСоединение.Получить(HTTPЗапрос); - это GET запрос,
а HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос); - это POST запрос.

В гет запросах нет тела, только урл. Странно что 1С просто выкидывает все данные, которые ты так старательно готовил и как не в чем ни бывало отправляет запрос. .NET например кидает исключение.
13 Kassern
 
11.11.20
16:36
(12) Это конечно все понятно и в СП это дело прописано, но тогда объясни какого художника через метод получить получается скачивать картинки к примеру для незащищенных соединений?
вот к примеру, накодил на коленке с первой попавшейся картинкой в инете:
Соединение=Новый HTTPСоединение("v.900igr.net",10);
Запрос=Новый HTTPЗапрос("/datas/schjot/Slozhenie-do-10-1.files/0007-007-22-4.jpg");
ФайлКартинки=Соединение.Получить(Запрос);
ДД=ФайлКартинки.ПолучитьТелоКакДвоичныеДанные();
ДД.Записать(КаталогЗаписи+"\тест_картинки.jpeg");
14 Kassern
 
11.11.20
16:41
(13) чет я туплю, для https только что проверил тоже канает. Раньше помню проблема была, приходилось код переделывать, может что поменялось. Но лучше все же явно прописывать метод, который хочешь вызвать
15 oleg_km
 
11.11.20
19:16
Не знаю. С инетом работаю через .NET HTTPClient
16 телега
 
12.11.20
15:27
(11) Да, вполне возможно. Просто тот же Постман отправлял полностью рабочую картинку и гетом и постом, это меня и ввело в заблуждение, ну и плюс: когда я получал тело как строку, то видел все свои денные в 1С, не ожидал такой подлости от программы.
17 телега
 
13.11.20
19:05
В очередной раз убеждаюсь в том насколько 1С криво работает с Интернетом, хотя они типа и пытаются быть модными и интернетными.

В общем решил отправить мультипартом обычное сообщение. Опять же - Постман, все дела...
Далее собираю в 1С, запускаю... 504 таймаут.
секция chat_id есть, секция text есть, баундри установлены, в конце "--", отправка через HTTPСоединение.ВызватьHTTPМетод("POST",HTTPЗапрос), хотя и просто ОтправитьДляОбработки то же самое.
Геты не работают: 1С тогда режет тело.
Какая гадость эта ваша заливная рыба.
18 acht
 
13.11.20
20:03
(17) > В очередной раз убеждаюсь
Бееееедненький
19 acht
 
13.11.20
20:07
У тебя UTF-то с BOM, без BOM, специалист?
20 телега
 
13.11.20
20:35
(19) Я делаю через УстановитьИмяФайлаТела там нет BOM. Сделано это для универсальности: как для сообщений, так и для файлов.
Но даже если через УстановитьТелоИзСтроки то ни так ни так не работает.
вот образец:

------ca4f33c0-6b9e-4d79-a9c5-bbc69478f139
Content-Disposition: form-data; name="chat_id"

376868390
------ca4f33c0-6b9e-4d79-a9c5-bbc69478f139
Content-Disposition: form-data; name="text"

get
------ca4f33c0-6b9e-4d79-a9c5-bbc69478f139--

кусок кода:

    HTTPЗапрос = Новый HTTPЗапрос;
    Заголовки = Новый Соответствие;
    
    HTTPЗапрос.Заголовки.Вставить("Connection", "keep-alive");
    HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary="+Boundary);
    
    //HTTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
    HTTPЗапрос.УстановитьТелоИзСтроки(ТекстДляОтправки,КодировкаТекста.UTF8,ИспользованиеByteOrderMark.НеИспользовать); //тут было и использовать и не использовать
    HTTPЗапрос.АдресРесурса = СтрокаСоединения;
    
    ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(Новый СертификатКлиентаWindows, Новый СертификатыУдостоверяющихЦентровWindows);
    HTTPСоединение = Новый HTTPСоединение(СерверTg,443,,,,3,ЗащищенноеСоединение);
    
    Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
21 oleg_km
 
13.11.20
20:40
Посмотри через фиддлер, увидишь в чем разница
22 телега
 
13.11.20
21:36
(21) Забавно...  + Символы.ВК + Символы.ПС а не + Символы.ПС
Почему же везде пишут только ПС?