Привет всем!
Есть API, в который нужно передать экселевский файл...
Написал уже 2мя разными способами, а ответ один и тот же, вернее ошибка: "Должен быть отправлен файл в поле"
Хотя в поле всё указано, разработчики со стороны API не могут внятно ничем помочь, показали рабочий код на cURL и на это всё.
Может тут у кого идеи возникнут в чём беда:
Итак,
Вариант оправки №1, через ПотокДанных():
ФайлДанных = "D:/11111111_ACC.xlsx";
Если ФайлДанных = Неопределено тогда
Возврат;
КонецЕсли;
БинДанные = Новый ДвоичныеДанные(ФайлДанных);
Токен = ПолучитьТокен();
Соединение = ПолучитьСоединение();
Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
ПотокТело = Новый ПотокВПамяти();
ЗаписьДанных = Новый ЗаписьДанных(ПотокТело);
ЗаписьДанных.ЗаписатьСтроку("");
ЗаписьДанных.ЗаписатьСтроку("--"+Boundary);
ЗаписьДанных.Записать(СоздатьСообщение_Файл("file", ФайлДанных, БинДанные));
ЗаписьДанных.ЗаписатьСтроку("--"+Boundary+"--");
ЗаписьДанных.Закрыть();
ДвоичныеДанныеТело = ПотокТело.ЗакрытьИПолучитьДвоичныеДанные();
Заголовки = Новый Соответствие;
Заголовки.Вставить("Accept","application/json");
Заголовки.Вставить("Authorization","Bearer " + Токен);
Заголовки.Вставить("Content-Type","multipart/form-data; boundary=" + "--" +boundary + "");
Запрос = Новый HTTPЗапрос("/api/v1/dealers/12345678/accessories/",Заголовки);
Запрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеТело);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Результат = Ответ.ПолучитьТелоКакСтроку();
Функция СоздатьСообщение_Файл(ИмяСообщения, ИмяФайла, ДвоичныеДанные)
Поток = Новый ПотокВПамяти();
ЗаписьДанных = Новый ЗаписьДанных(Поток);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=" + ИмяСообщения + "; filename=" + ИмяФайла+"");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/vnd.ms-excel"+ Символы.ПС );
ЗаписьДанных.Записать(ДвоичныеДанные);
ЗаписьДанных.Закрыть();
Возврат Поток.ЗакрытьИПолучитьДвоичныеДанные();
КонецФункции
Показать
Вариант оправки №2, через Объединение файлов:
ФайлДанных = "D:/11111111_ACC.xlsx";
Если ФайлДанных = Неопределено тогда
Возврат;
КонецЕсли;
БинДанные = Новый ДвоичныеДанные(ФайлДанных);
Токен = ПолучитьТокен();
Соединение = ПолучитьСоединение();
Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
ИмяФайлаОтправки = КаталогВременныхФайлов() + "post.txt";
ИмяФайлаДляЗагрузки = ФайлДанных;
МассивФайловДляОбъединения = Новый Массив;
//Формируем начальный фрагмент файла POST-запроса
ИмяФайлаОтправкиНачало = ПолучитьИмяВременногоФайла("txt");
ФайлОтправкиНачало = Новый ЗаписьТекста(ИмяФайлаОтправкиНачало, КодировкаТекста.UTF8, Символы.ПС, Ложь);
//Определяем раздел двоичных данных
ФайлОтправкиНачало.ЗаписатьСтроку("--" + Boundary);
//Указываем имя файла для передачи
ФайлОтправкиНачало.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" + ИмяФайлаДляЗагрузки + """");
//Указываем тип передаваемых данных.
ФайлОтправкиНачало.ЗаписатьСтроку("Content-Type: application/vnd.ms-excel");
ФайлОтправкиНачало.ЗаписатьСтроку("");
ФайлОтправкиНачало.Закрыть();
МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиНачало);
//Копируем файл для загрузки во временный и добавляем в массив файлов для объединения
ИмяФайлаДляЗагрузкиВременный = ПолучитьИмяВременногоФайла("tmp");
КопироватьФайл(ИмяФайлаДляЗагрузки, ИмяФайлаДляЗагрузкиВременный);
МассивФайловДляОбъединения.Добавить(ИмяФайлаДляЗагрузкиВременный);
//Формируем конечный фрагмент файла POST-запроса
ИмяФайлаОтправкиКонец = ПолучитьИмяВременногоФайла("txt");
ФайлОтправкиКонец = Новый ЗаписьТекста(ИмяФайлаОтправкиКонец, КодировкаТекста.UTF8, Символы.ПС, Ложь);
//Завершение раздела двоичных данных
ФайлОтправкиКонец.ЗаписатьСтроку("");
ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary);
ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary + "--");
ФайлОтправкиКонец.Закрыть();
МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиКонец);
ОбъединитьФайлы(МассивФайловДляОбъединения, ИмяФайлаОтправки);
//*************************************
Заголовки = Новый Соответствие;
Заголовки.Вставить("Accept","application/json");
Заголовки.Вставить("Authorization","Bearer " + Токен);
Заголовки.Вставить("Content-Type","multipart/form-data; boundary=" + "--" +boundary + "");
Запрос = Новый HTTPЗапрос("/api/v1/dealers/12345678/accessories/",Заголовки);
Запрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Результат = Ответ.ПолучитьТелоКакСтроку();
Показать
В обоих случаях возвращается :
"Должен быть отправлен файл в поле"
Тех. поддержка со стороны API прислал рабочий код на cURL:
А вообще тут на инфостарте где-то библиотеку процедур и функций 1С для HTTP видел - там должно быть совсем просто, на готовом и проверенном. Вроде эта https://infostart.ru/public/709325/
И так, для тех кто в теме. Техподдержка увы ничем не помогла.... Варианты перепробовал разные...
Все оказалось тривиально - В коде , который предложен в документации (это Вариант оправки №2, через Объединение файлов) , формирование тела письма происходит в кодировке UTF8, в то время как сервер не понимает ее, а принимает кодировку ANSI. Достаточно было изменить в функции ЗаписьТекста параметр КодировкаТекста UTF8 на ANSI и все работает!!!!
Здесь:
ФайлОтправкиНачало = Новый ЗаписьТекста(ИмяФайлаОтправкиНачало, КодировкаТекста.UTF8);
//Заменить на --->
ФайлОтправкиНачало = Новый ЗаписьТекста(ИмяФайлаОтправкиНачало, КодировкаТекста.ANSI);
и здесь:
ФайлаОтправкиКонец = Новый ЗаписьТекста(ИмяФайлаОтправкиКонец, КодировкаТекста.UTF8);
//Заменить на --->
ФайлаОтправкиКонец = Новый ЗаписьТекста(ИмяФайлаОтправкиКонец, КодировкаТекста.ANSI);
В варианте 1 с потоком таже проблема - по умолчанию файл в кодировке UTF8. В параметрах функции ЗаписьДанных необходимо указать кодировку ANSI....
Дело не в кодировке, тем более, что на первых 127 символах (в т.ч. английские буквы, цифры, символы над цифрами клавиатуры) кодировка UTF8 тождественна ANSI (ASCII). Дело в BOM (Byte Order Mark). Эска по-умолчанию дописываает BOM для кодировки UTF-8, надо специально указать, что BOM не нужен. Т.е. в конструкторе последний параметр <ЗаписатьBOM> надо Ложь поставить для кодировки UTF-8
Новый ЗаписьТекста(<Поток>, <Кодировка>, <РазделительСтрок>, <КонвертируемыйРазделительСтрок>, <ЗаписатьBOM>)
Меня как-то php-прогер попросил данные передавать в UTF-8, но сервер никак не мог их принять, пока не выяснили, что ему BOM мешает. Убрали BOM и заработало.
Спасибо. Очень помогли все выкладки. Ситуация один в один как в шапке. Помог вариант 2. Понадобилось изменить минусы "--", убрал в самом начале начальные минусы, и убрал в конце конечные минусы.