Сохранение файла из потока данных от API внешней системы

1. MrGreenDragonZz 03.08.21 08:42 Сейчас в теме
Работаю с внешним API. Отправляю запрос и получаю ответ. В описании: "Метод позволяет скачать файл. При скачивании содержимое файла отдаётся в виде потока, название файла отдаётся в HTTP заголовке Content-Disposition." В потоке файл и я не могу разобраться как его сохранить.
Прикрепленные файлы:
По теме из базы знаний
Найденные решения
10. sivin-alexey 508 03.08.21 11:56 Сейчас в теме
Тут используется старый синтаксис HTTP_Соединение.Получить(АдресСкрипта, ИмяФайлаОтвета).

Лучше использовать новый:

Ответ = HTTP_Соединение.Получить(АдресСкрипта);
Если Ответ.КодСостояния=200 Тогда
     ДвоичныеДанные = Ответ.ПолучитьТелоКакДвоичныеДанные(); 

     //если возвращается текст, то можно двоичные данные преобразовать в строку:
     Текст  = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанные,КодировкаТекста.UTF8); 

     // Ответ.Заголовки["Content-Type"] - поможет определить тип данных в теле ответа
   
КонецЕсли;
Показать
MrGreenDragonZz; DJ_Codebase; +2 Ответить
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. sivin-alexey 508 03.08.21 08:58 Сейчас в теме
Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
ДвоичныеДанные = Ответ.ПолучитьТелоКакДвоичныеДанные();
3. MrGreenDragonZz 03.08.21 09:32 Сейчас в теме
(2) {RetailCRMИнтеграция Обработка.crm_RetailCRMОбработка.МодульОбъекта(755)}: Метод объекта не обнаружен (ПолучитьТелоКакДвоичныеДанные). Я так понял, что запрос делается в формате JSON. Возвращается массив.
4. platonov.e 159 03.08.21 10:02 Сейчас в теме
(3) Значит у вас в Ответ, совсем не ответ)
5. sivin-alexey 508 03.08.21 10:42 Сейчас в теме
(3)
1. Уточнение: т.к. метод GET, то нужно использовать:

Ответ = HTTPСоединение.Получить(HTTPЗапрос);
ДвоичныеДанные = Ответ.ПолучитьТелоКакДвоичныеДанные();


2. Как у вас выполняется http-запрос? Код в студию

3. В API написано "в виде потока", т.е. никак не JSON.
7. MrGreenDragonZz 03.08.21 11:43 Сейчас в теме
(5)
&НаСервере
Функция ПолучитьФайлыПоИД(МассивИД) Экспорт


Если МассивИД.Количество() = 0 Тогда
Возврат Неопределено;
КонецЕсли;

МассивФайлов = Новый Массив;

СтрокаФайлИД = "";
Для Каждого ФайлИД из МассивИД Цикл
СтрокаФайлИД = СтрокаФайлИД + "filter[orderIds][]=" + ФайлИД + "&";
КонецЦикла;

СтрокаФайлИД = ?(Прав(СтрокаФайлИД, 1) = "&", Лев(СтрокаФайлИД, СтрДлина(СтрокаФайлИД) - 1), СтрокаФайлИД);

ApiKey = crm_RetailCRMОбщий.ПолучитьЗначениеКонстанты("КлючCRM");
АдресСкриптаФайл = "/api/v5/files?" + СтрокаФайлИД + "&limit=100&apiKey=" + ApiKey;

ОтветФайл = ЗапросCRM(АдресСкриптаФайл);

Для Каждого Файл из ОтветФайл["files"] Цикл
АдресСкриптаЗагрузкиФайла = "/api/v5/files/" + Файл["id"] + "/download?apiKey=" + ApiKey;
ЗагрузкаФайл = ЗапросCRM(АдресСкриптаЗагрузкиФайла);
МассивФайлов.Добавить(Файл);
КонецЦикла;

Возврат МассивФайлов

КонецФункции
Показать
6. пользователь 03.08.21 11:43
Сообщение было скрыто модератором.
...
8. sivin-alexey 508 03.08.21 11:45 Сейчас в теме
(6) а функция ЗапросCRM() ?
9. MrGreenDragonZz 03.08.21 11:46 Сейчас в теме
&НаСервере
Функция ЗапросCRM(АдресСкрипта)
	
	Сообщить("Запрос к RetailCRM ...");	
	ответ = crm_RetailCRMОбщий.HTTPзапросGET(crm_RetailCRMОбщий.ПолучитьЗначениеКонстанты("ИмяСервера"),АдресСкрипта);		
	Сообщить("Разбор ответа ...");
	
	Возврат crm_RetailCRMОбщий.UnJSON(ответ);
	
КонецФункции

Функция HTTPзапросGET(АдресСервера,АдресСкрипта) Экспорт
	
	ssl = Новый ЗащищенноеСоединениеOpenSSL(Неопределено,Неопределено);
	
	HTTP_Соединение = Новый HTTPСоединение(АдресСервера,,,,,,ssl);
	
	ИмяФайлаОтвета = ПолучитьИмяВременногоФайла();
	HTTP_Соединение.Получить(АдресСкрипта,ИмяФайлаОтвета);	
	ФайлОтвета = Новый Файл(ИмяФайлаОтвета);
	ТекстОтвета = Новый ТекстовыйДокумент();
	ТекстОтвета.Прочитать(ИмяФайлаОтвета,"utf-8");
	
	возврат ТекстОтвета.ПолучитьТекст();
	
КонецФункции
Показать
10. sivin-alexey 508 03.08.21 11:56 Сейчас в теме
Тут используется старый синтаксис HTTP_Соединение.Получить(АдресСкрипта, ИмяФайлаОтвета).

Лучше использовать новый:

Ответ = HTTP_Соединение.Получить(АдресСкрипта);
Если Ответ.КодСостояния=200 Тогда
     ДвоичныеДанные = Ответ.ПолучитьТелоКакДвоичныеДанные(); 

     //если возвращается текст, то можно двоичные данные преобразовать в строку:
     Текст  = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанные,КодировкаТекста.UTF8); 

     // Ответ.Заголовки["Content-Type"] - поможет определить тип данных в теле ответа
   
КонецЕсли;
Показать
MrGreenDragonZz; DJ_Codebase; +2 Ответить
11. DJ_Codebase 03.08.21 12:11 Сейчас в теме
(10) Он то не старый, просто как один из вариантов. Я и не думал, что хто то его использует ч-з врем. файл, а оказывается используют.
12. sivin-alexey 508 03.08.21 12:17 Сейчас в теме
(11) Именно старый. Использовался до 8.3.3. Оставлен для совместимости.
13. DJ_Codebase 03.08.21 12:22 Сейчас в теме
(12) Спасибо, буду знать. Не доводилось работать с http на ранних платформах
14. MrGreenDragonZz 03.08.21 12:23 Сейчас в теме
(11) Предложено в рамкам расширения в начале этого года. Вероятно переработанное решение для старых систем. Никто не хочет писать с нуля, поэтому такие вещи встречаются и будут вероятно встречаться.
15. DJ_Codebase 03.08.21 12:35 Сейчас в теме
(14) Наверно будут, но я бы переписывал такую конструкцию без использования вр. файла. Это ж нетрудно
16. MrGreenDragonZz 03.08.21 14:59 Сейчас в теме
(15) Да, займусь этим, пока занят другими задачами. Как опробую - дам знать. Для меня это пока тёмный лес.
17. MrGreenDragonZz 12.08.21 09:55 Сейчас в теме
(10)
Ответ
Сделал так:
Функция HTTPзапросGETfiles(АдресСервера,АдресСкрипта) Экспорт
	
	SSL = Новый ЗащищенноеСоединениеOpenSSL(Неопределено,Неопределено);
	HTTP_Соединение = Новый HTTPСоединение(АдресСервера,,,,,,SSL);
	ИмяФайлаОтвета = ПолучитьИмяВременногоФайла();
	Ответ = HTTP_Соединение.Получить(АдресСкрипта);
	Если Ответ.КодСостояния = 200 Тогда
		ДвоичныеДанные = Ответ.ПолучитьТелоКакДвоичныеДанные();
	КонецЕсли;
	
	Возврат ДвоичныеДанные;
	
КонецФункции
Показать

Но ДвоичныеДанные = Неопределено, хотя в Ответ приходят данные.
19. antz 12.08.21 12:31 Сейчас в теме
(17) А http-запрос где?

SSL = Новый ЗащищенноеСоединениеOpenSSL(Неопределено,Неопределено);
HTTP_Соединение = Новый HTTPСоединение(АдресСервера,,,,,,SSL);
Запрос  = Новый HTTPЗапрос(АдресСкрипта);
Ответ = HTTP_Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
    ДвоичныеДанные = Ответ.ПолучитьТелоКакДвоичныеДанные();
КонецЕсли; 
MrGreenDragonZz; +1 Ответить
20. MrGreenDragonZz 12.08.21 12:33 Сейчас в теме
(19) В каком смысле? Всё в коде вроде...
21. MrGreenDragonZz 12.08.21 12:45 Сейчас в теме
(19) Всё, понял, что не так. Вроде получилось. Но файл не типизирован.
22. DJ_Codebase 12.08.21 12:55 Сейчас в теме
(21) Какой файл? вы должны сами знать, какого типа двоичные данные получаете, либо смотреть в заголовках ответа, если сервис это передает
23. spacecraft 12.08.21 12:56 Сейчас в теме
(21)
Но файл не типизирован

Конечно, ведь получили просто двоичные данные (набор байт).
Из описания API метода: "название файла отдаётся в HTTP заголовке Content-Disposition"
Этих данных должно быть достаточно.
24. MrGreenDragonZz 12.08.21 13:21 Сейчас в теме
(23) Получаю Ответ.Заголовки["Content-Disposition"]. Это строка, но СтрНайти там не работает. Выдает 0 на любой параметр.
25. antz 12.08.21 13:27 Сейчас в теме
26. MrGreenDragonZz 12.08.21 13:36 Сейчас в теме
(25) СтрНайти("filename",Ответ.Заголовки["Content-Disposition"]) возвращает 0, хотя значение "attachment; filename=test.docx; filename*=utf-8''%D0%A2%D0%B5%D1%81%D1%82.docx"
27. spacecraft 12.08.21 13:39 Сейчас в теме
(26) параметры СтрНайти поменять местами. Вначале Где ищем, затем что ищем.
28. MrGreenDragonZz 12.08.21 14:01 Сейчас в теме
(27) Вот это фэйл XD Всё, мозг закипел... Спасибо.
18. MrGreenDragonZz 12.08.21 11:29 Сейчас в теме
Вот такую структуру возвращает
Прикрепленные файлы:
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот