Отправка файла POST запросом
Доброго времени суток, подскажите а то уже всю головку сломал, перепробовал разные внешние комоненты в том числе WinHttp.WinHttpRequest.5.1, ничего не получается, такое ощущение что формат данных для передачи не правильные, сервер ожидает UTF-8. Тот же самый файл, тот же самый запрос отправляется POSTMAN и Python'ом без проблем.
Есть задача, отправить файл по API на сервер POST Запросом.
Выполняю:
В ответ приходит:
400
{"detail":"There was an error parsing the body"}
Есть задача, отправить файл по API на сервер POST Запросом.
Выполняю:
ИмяФайлаДляЗагрузки = 1.pdf;
дд = ПолучитьИзВременногоХранилища(Адр);
Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
РазделительСтрок = Символ(10)+Символ(13);
Данные = ПолучитьСтрокуИзДвоичныхДанных(дд);
ЗапросWeb = Новый HTTPЗапрос("/decodefile/");
ЗапросWeb.Заголовки.Вставить("Content-Type","multipart/form-data; boundary=" + Boundary+"; charset=utf-8");
ЗапросWeb.Заголовки.Вставить("Accept-Charset", "utf-8");
ЗапросWeb.Заголовки.Вставить("Content-Charset", "utf-8");
ТелоЗапроса = ЗапросWeb.ПолучитьТелоКакПоток();
ЗаписьДанных = Новый ЗаписьДанных(ТелоЗапроса, КодировкаТекста.UTF8, ПорядокБайтов.LittleEndian, РазделительСтрок, "", Ложь);
ЗаписьДанных.ЗаписатьСтроку("--" + Boundary + РазделительСтрок);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" +ИмяФайлаДляЗагрузки+"""");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/pdf; charset=utf-8");
ЗаписьДанных.Записать(дд);
ЗаписьДанных.ЗаписатьСтроку(РазделительСтрок);
ЗаписьДанных.ЗаписатьСтроку("--" + Boundary + "--" + РазделительСтрок);
ЗаписьДанных.Закрыть();
Соединение = Новый HTTPСоединение("10.10.61.30",9990,,,,,,);
ОтветWeb = Соединение.ОтправитьДляОбработки(ЗапросWeb);
Сообщить(ОтветWeb.КодСостояния);
ссответа = ОтветWeb.ПолучитьТелоКакСтроку("UTF-8");
Сообщить(ссответа);
ПоказатьВ ответ приходит:
400
{"detail":"There was an error parsing the body"}
По теме из базы знаний
- Передача файлов и данных на веб-сервер средствами 1С:Предприятие 8.X методом POST
- Отправка произвольного файла POST запросом с параметрами на сервер
- Отправка HTTP запроса в УТМ ЕГАИС. Код функции + обработка.
- Отправка файлов через SOAP. SOAP with attachments, MTOM
- Обмен с сайтом посредством Post-запроса, json
Найденные решения
(10) Ну если так уж хочется без готовой библиотеки - то что я заметил:
должно быть
Сам РазделительСтрок не тот 10+13. RFC2045 -
Вообще когда я файлами мультипарт собирал - получалось, что ему достаточно ПС (10) - хоть и отклоняется от RFC - но проходило.
Ибо я использовал обычную ЗаписьТекста, которая по умолчанию в конце строки ставит только ПС.
ЗаписьДанных.ЗаписатьСтроку("--" + Boundary + РазделительСтрок);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" +ИмяФайлаДляЗагрузки+"""");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/pdf; charset=utf-8");должно быть
ЗаписьДанных.ЗаписатьСтроку("--" + Boundary);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" +ИмяФайлаДляЗагрузки+"""");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/pdf; charset=utf-8" + РазделительСтрок);Сам РазделительСтрок не тот 10+13. RFC2045 -
The term CRLF, in this set of documents, refers to the sequence of octets corresponding to the two US-ASCII characters CR (decimal value 13) and LF (decimal value 10)
Т.е. должен быть 13+10.
Вообще когда я файлами мультипарт собирал - получалось, что ему достаточно ПС (10) - хоть и отклоняется от RFC - но проходило.
Ибо я использовал обычную ЗаписьТекста, которая по умолчанию в конце строки ставит только ПС.
ЗаписьТекста = Новый ЗаписьТекста(имяФайлаСПараметрами, "CESU-8"); //utf-8 без bom
// параметр "photo"
ИмяФайла = Строка(Новый УникальныйИдентификатор()) + "." + РасширениеФайлаКартинки;
ЗаписьТекста.ЗаписатьСтроку("--"+boundary);
ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""photo""; filename=""" + ИмяФайла + """");
ЗаписьТекста.ЗаписатьСтроку("Content-Type: image/"+РасширениеФайлаКартинки);
ЗаписьТекста.ЗаписатьСтроку("");
// дальше присоединялись двоичные данные картинки
ПоказатьОстальные ответы
Подписаться на ответы
Инфостарт бот
Сортировка:
Древо развёрнутое
Свернуть все
(1)
Чтобы не гадать, что не так, надо смотреть в чем отличия при правильной отправке и при не правильной.
Это удобно и наглядно можно увидеть с помощью Fiddler'а.
подскажите а то уже всю головку сломал, перепробовал разные внешние комоненты в том числе WinHttp.WinHttpRequest.5.1, ничего не получается, такое ощущение что формат данных для передачи не правильные, сервер ожидает UTF-8. Тот же самый файл, тот же самый запрос отправляется POSTMAN и Python'ом без проблем.
Чтобы не гадать, что не так, надо смотреть в чем отличия при правильной отправке и при не правильной.
Это удобно и наглядно можно увидеть с помощью Fiddler'а.
(5) Не только кодировка отличается.
Вот этого нет в рабочем скрине:
"Content-Type: application/pdf; charset=utf-8"
Попробуйте другой кодировкой записать, windows-1251, например, или ANSI.
П.С. Стоит сравнивать запросы с закладки RAW - в ней будут видны как заголовки, так и тело.
Вот этого нет в рабочем скрине:
"Content-Type: application/pdf; charset=utf-8"
Попробуйте другой кодировкой записать, windows-1251, например, или ANSI.
П.С. Стоит сравнивать запросы с закладки RAW - в ней будут видны как заголовки, так и тело.
(9) Обычно, при наличии правильного и HTTP запроса в фидлере не составляет сложности привести к нужному виду НTTP запрос в 1С. Сравнить заголовки, сравнить тело, что отличается - исправить.
По поводу кодировки при передаче файла - с таким не сталкивался, может там просто файлы разные?
Приложите RAW правильного запроса и файл для отправки для примера.
Завтра будет время, могу посмотреть.
По поводу кодировки при передаче файла - с таким не сталкивался, может там просто файлы разные?
Приложите RAW правильного запроса и файл для отправки для примера.
Завтра будет время, могу посмотреть.
(9) Это фидлер не понимает что Вы шлете. В неверном запросе лишний "Content-Type: application/pdf; charset=utf-8", которого вообще нет в рабочем скрине. И из-за неверного РазделительСтрок = Символ(10)+Символ(13); (нужен наоборот 13+10) у фидлера видимо крыша едет.
(5)Еще можно попробовать, без записи в поток.
...
ИмяФайла1 = ПолучитьИмяВременногоФайла("txt");
ЗаписьТекста = Новый ЗаписьТекста(ИмяФайла1);
ЗаписьТекста.ЗаписатьСтроку("--"+boundary);
ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" +ИмяФайлаДляЗагрузки+"""");
ЗаписьТекста.ЗаписатьСтроку("");
ЗаписьТекста.Закрыть();
ИмяФайла2 = ПолучитьИмяВременногоФайла("txt");
ИмяФайлаСДанными = ПолучитьИмяВременногоФайла("PDF");
ДД.Записать(ИмяФайлаСДанными );
ЗаписьТекста = Новый ЗаписьТекст(ИмяФайла2);
ЗаписьТекста.ЗаписатьСтроку("");
ЗаписьТекста.ЗаписатьСтроку("--"+boundary+"--");
ЗаписьТекста.Закрыть();
ИмяФайлаОтправки = ПолучитьИмяВременногоФайла("out");
МассивФайлов = Новый Массив;
МассивФайлов.Добавить(ИмяФайла1);
МассивФайлов.Добавить(ИмяФайлаСДанными);
МассивФайлов.Добавить(ИмяФайла2);
ОбъединитьФайлы(МассивФайлов, ИмяФайлаОтправки);
ЗапросWeb.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
...
Показать
(8) На АПИ телеграма такое не проходило из-за того, что Новый ЗаписьТекста(ИмяФайла1); устананавливал BOM - ненужные байты в начале. Их нужно либо потом убирать, либо как вариант Новый ЗаписьТекста(имяФайлаСПараметрами, "CESU-8"); - суррогат УТФ8 без БОМ.
(13)Удалить BOM не сложно.
После закрытия записи текста:
После закрытия записи текста:
ДДанные = Новый ДвоичныеДанные(ИмяФайла1);
Если Сред(ДДанные, 1, 8) = "EF BB BF" Тогда
Строка64 = Base64Строка(ДДанные);
Строка64 = Прав(Строка64,СтрДлина(Строка64)-4); // Удаляем 3 символа BOM, для кодировки UTF-8
ДДанные = Base64Значение(Строка64);
КонецЕсли;
(14)
А эска дальше FFFF вообще не работает, поэтому в контексте 1С можно сказать, что UTF-8 и CESU-8 - это одинаковые кодировки.
Сообщения:
65 534
65 535
-1
-1
-1
CESU-8 A Unicode code point from the Basic Multilingual Plane (BMP), i.e. a code point in the range U+0000 to U+FFFF, is encoded in the same way as in UTF-8
А эска дальше FFFF вообще не работает, поэтому в контексте 1С можно сказать, что UTF-8 и CESU-8 - это одинаковые кодировки.
Сообщить(КодСимвола(Символ(65534)));
Сообщить(КодСимвола(Символ(65535)));//FFFF
Сообщить(КодСимвола(Символ(65536)));
Сообщить(КодСимвола(Символ(65537)));
Сообщить(КодСимвола(Символ(65538)));
Сообщения:
65 534
65 535
-1
-1
-1
(11)Решение было на столько близко, что даже в глаза не попадало, РазделительСтрок был не по правилам собран, мне подсказал , исправил его и все пошло, уж не знаю с чем ещё дальше столкнусь, но все ответы на мой вопрос дали ответы на многие тонкости, спасибо большое за активность. Если честно первый раз в жизни на форумах задаю вопросы, только отвечал, никогда не верил в этой, но благодаря всем вам у меня поменялось мнение кардинально....
Дальше буду мучать ЧестныйЗнак и Диадок, там уже подписи, шифрования всякие)Но там вроде половина уже сделана, т.е. авторизации, получения документов и т.д., теперь на очереди Отправка и тот же Мультипарт, но думаю (надеюсь), что теперь пойдут дела в гору))
На просторах интернета мало описания, как получится, постараюсь выложить примеры, для таких как я на будущее)) попытаюсь изложить все замечания и предложения что были предложены мне тут...
Ещё раз огромное спасибо....
Дальше буду мучать ЧестныйЗнак и Диадок, там уже подписи, шифрования всякие)Но там вроде половина уже сделана, т.е. авторизации, получения документов и т.д., теперь на очереди Отправка и тот же Мультипарт, но думаю (надеюсь), что теперь пойдут дела в гору))
На просторах интернета мало описания, как получится, постараюсь выложить примеры, для таких как я на будущее)) попытаюсь изложить все замечания и предложения что были предложены мне тут...
Ещё раз огромное спасибо....
(1)Вообще странное решение с этим РазделителемСтрок, и сам он неверный (нужно наоборот Символ(13)+Символ(10)) и можно вообще без него обойтись - эска сама по умолчанию все нормально перенесет.
Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
Данные = ПолучитьСтрокуИзДвоичныхДанных(дд);
ЗапросWeb = Новый HTTPЗапрос("/decodefile/");
ЗапросWeb.Заголовки.Вставить("Content-Type","multipart/form-data; boundary=" + Boundary + "; charset=utf-8");
ТелоЗапроса = ЗапросWeb.ПолучитьТелоКакПоток();
ЗаписьДанных = Новый ЗаписьДанных(ТелоЗапроса, КодировкаТекста.UTF8, ПорядокБайтов.LittleEndian, , , Ложь);
ЗаписьДанных.ЗаписатьСтроку("--" + Boundary);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" +ИмяФайлаДляЗагрузки+"""");
ЗаписьДанных.ЗаписатьСтроку("");//перед данными дополнительный CRLF
ЗаписьДанных.Записать(дд);
ЗаписьДанных.ЗаписатьСтроку("");//бандери с новой строки
ЗаписьДанных.ЗаписатьСтроку("--" + Boundary + "--");
ЗаписьДанных.Закрыть(); Показать
как на счет
А еще ресурс какой то странный. Он ведет ведь в каталог
ЗапросWeb.УстановитьТелоИзДвоичныхДанных(дд)А еще ресурс какой то странный. Он ведет ведь в каталог
(8)
(8)
(8)С этого мы начинали:) Не робит, у нас 3 API, Диадок, Честный знак и этот местный сервак) никуда не получилось) уже месяц бадаемся, силы на исходе
(5)Еще можно попробовать, без записи в поток.
...
ИмяФайла1 = ПолучитьИмяВременногоФайла("txt");
ЗаписьТекста = Новый ЗаписьТекста(ИмяФайла1);
ЗаписьТекста.ЗаписатьСтроку("--"+boundary);
ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" +ИмяФайлаДляЗагрузки+"""");
ЗаписьТекста.ЗаписатьСтроку("");
ЗаписьТекста.Закрыть();
ИмяФайла2 = ПолучитьИмяВременногоФайла("txt");
ИмяФайлаСДанными = ПолучитьИмяВременногоФайла("PDF");
ДД.Записать(ИмяФайлаСДанными );
ЗаписьТекста = Новый ЗаписьТекст(ИмяФайла2);
ЗаписьТекста.ЗаписатьСтроку("");
ЗаписьТекста.ЗаписатьСтроку("--"+boundary+"--");
ЗаписьТекста.Закрыть();
ИмяФайлаОтправки = ПолучитьИмяВременногоФайла("out");
МассивФайлов = Новый Массив;
МассивФайлов.Добавить(ИмяФайла1);
МассивФайлов.Добавить(ИмяФайлаСДанными);
МассивФайлов.Добавить(ИмяФайла2);
ОбъединитьФайлы(МассивФайлов, ИмяФайлаОтправки);
ЗапросWeb.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
...
Показать...
ИмяФайла1 = ПолучитьИмяВременногоФайла("txt");
ЗаписьТекста = Новый ЗаписьТекста(ИмяФайла1);
ЗаписьТекста.ЗаписатьСтроку("--"+boundary);
ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" +ИмяФайлаДляЗагрузки+"""");
ЗаписьТекста.ЗаписатьСтроку("");
ЗаписьТекста.Закрыть();
ИмяФайла2 = ПолучитьИмяВременногоФайла("txt");
ИмяФайлаСДанными = ПолучитьИмяВременногоФайла("PDF");
ДД.Записать(ИмяФайлаСДанными );
ЗаписьТекста = Новый ЗаписьТекст(ИмяФайла2);
ЗаписьТекста.ЗаписатьСтроку("");
ЗаписьТекста.ЗаписатьСтроку("--"+boundary+"--");
ЗаписьТекста.Закрыть();
ИмяФайлаОтправки = ПолучитьИмяВременногоФайла("out");
МассивФайлов = Новый Массив;
МассивФайлов.Добавить(ИмяФайла1);
МассивФайлов.Добавить(ИмяФайлаСДанными);
МассивФайлов.Добавить(ИмяФайла2);
ОбъединитьФайлы(МассивФайлов, ИмяФайлаОтправки);
ЗапросWeb.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
...
(8)
(8)С этого мы начинали:) Не робит, у нас 3 API, Диадок, Честный знак и этот местный сервак) никуда не получилось) уже месяц бадаемся, силы на исходе
(10) Ну если так уж хочется без готовой библиотеки - то что я заметил:
должно быть
Сам РазделительСтрок не тот 10+13. RFC2045 -
Вообще когда я файлами мультипарт собирал - получалось, что ему достаточно ПС (10) - хоть и отклоняется от RFC - но проходило.
Ибо я использовал обычную ЗаписьТекста, которая по умолчанию в конце строки ставит только ПС.
ЗаписьДанных.ЗаписатьСтроку("--" + Boundary + РазделительСтрок);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" +ИмяФайлаДляЗагрузки+"""");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/pdf; charset=utf-8");должно быть
ЗаписьДанных.ЗаписатьСтроку("--" + Boundary);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" +ИмяФайлаДляЗагрузки+"""");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/pdf; charset=utf-8" + РазделительСтрок);Сам РазделительСтрок не тот 10+13. RFC2045 -
The term CRLF, in this set of documents, refers to the sequence of octets corresponding to the two US-ASCII characters CR (decimal value 13) and LF (decimal value 10)
Т.е. должен быть 13+10.
Вообще когда я файлами мультипарт собирал - получалось, что ему достаточно ПС (10) - хоть и отклоняется от RFC - но проходило.
Ибо я использовал обычную ЗаписьТекста, которая по умолчанию в конце строки ставит только ПС.
ЗаписьТекста = Новый ЗаписьТекста(имяФайлаСПараметрами, "CESU-8"); //utf-8 без bom
// параметр "photo"
ИмяФайла = Строка(Новый УникальныйИдентификатор()) + "." + РасширениеФайлаКартинки;
ЗаписьТекста.ЗаписатьСтроку("--"+boundary);
ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""photo""; filename=""" + ИмяФайла + """");
ЗаписьТекста.ЗаписатьСтроку("Content-Type: image/"+РасширениеФайлаКартинки);
ЗаписьТекста.ЗаписатьСтроку("");
// дальше присоединялись двоичные данные картинки
Показать
(12) Хотя нет, сейчас посмотрел - по умолчанию ЗаписьТекста.ЗаписатьСтроку везде в конце строки пишет байты 0D0A , т.е. символ.ВК+символ.ПС, они же Символ(13) + Символ(10). Это как раз то, что требует RFC2045 при формировании мультипарта.
(12)
Блииин дружище..... Спасибо огроооомное!!!!! Я получил 200, чуть со стула не упал, радости полные штаны!!!!)))) Разделить не правильный был, как ты и сказал)) стоило только поменять местами 10 и 13 и все пошло) а ещё убрал явное представление формата файла "ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/pdf; charset=utf-8" + РазделительСтрок);" заменил на "", судя по всему все формируется автоматически.....
Примного благодарен.. Честно...
Это был самый простой, местный, но думаю с остальными уже по накатанной пойдет, там ЧестныйЗнак и Диадок, думаю в общаг потом выложу куда нить, а то весь интернет облазил, как будто затирают все это....
РазделительСтрок
Блииин дружище..... Спасибо огроооомное!!!!! Я получил 200, чуть со стула не упал, радости полные штаны!!!!)))) Разделить не правильный был, как ты и сказал)) стоило только поменять местами 10 и 13 и все пошло) а ещё убрал явное представление формата файла "ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/pdf; charset=utf-8" + РазделительСтрок);" заменил на "", судя по всему все формируется автоматически.....
Примного благодарен.. Честно...
Это был самый простой, местный, но думаю с остальными уже по накатанной пойдет, там ЧестныйЗнак и Диадок, думаю в общаг потом выложу куда нить, а то весь интернет облазил, как будто затирают все это....
Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот
