|
multipart/form-data files | ☑ | ||
---|---|---|---|---|
0
SRM1C
22.12.20
✎
08:26
|
Функция СоздатьСообщение()
ВыборкаКартинок = Справочники.НоменклатураПрисоединенныеФайлы.Выбрать(); // Формируем основное составное сообщение Разделитель = Строка(новый УникальныйИдентификатор()); Результат = Новый Структура(); Заголовки = Новый Соответствие(); Результат.Вставить("Заголовки", Заголовки); Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + разделитель); Заголовки.Вставить("Authorization", "Basic b25lYzpzb21ldGhpbmdjcmVlcHk="); Тело = Новый ПотокВПамяти(); ЗаписьДанных = Новый ЗаписьДанных(Тело); ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель); Текст = СоздатьСообщение_Текст("productId",Строка(СсылкаНаНоменлкатуру.УникальныйИдентификатор())); ЗаписьДанных.Записать(текст); ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель); Пока ВыборкаКартинок.Следующий() Цикл ////////////// //Создаем вложенные сообщения //Каждое вложенное сообщение представлено экземпляром типа // ДвоичныеДанные //Это удобно, т.к. в данном случае внутренняя структура этих // сообщений нам не интересна Транспорт = СоздатьСообщение_Изображение("image",ВыборкаКартинок.Наименование+"."+ВыборкаКартинок.Расширение, ВыборкаКартинок.Ссылка); ЗаписьДанных.Записать(Транспорт); ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель + "--"); ///////////////// КонецЦикла; ЗаписьДанных.Закрыть(); ДанныеТела = Тело.ЗакрытьИПолучитьДвоичныеДанные(); Результат.Вставить("Тело", ДанныеТела); //Возврат Результат; Адрес = ПолучитьАдресСайта(); Ресурс = "/v1/product-images"; НТТР = Новый HTTPСоединение(Адрес, , , , , , Новый ЗащищенноеСоединениеOpenSSL(неопределено, неопределено)); НТТРЗапрос = Новый HTTPЗапрос(Ресурс,Результат.Заголовки); НТТРЗапрос.УстановитьТелоИзДвоичныхДанных(Результат.Тело); Рез = НТТР.ОтправитьДляОбработки(НТТРЗапрос); Если Число(Лев(Рез.КодСостояния,1)) >= 4 Тогда Ошибка = Рез.ПолучитьТелоКакСтроку(); КонецЕсли; КонецФункции // Возвращается HTTP-сообщение в виде ДвоичныеДанные Функция СоздатьСообщение_Текст(ИмяСообщения, Текст) Поток = Новый ПотокВПамяти(); ЗаписьДанных = Новый ЗаписьДанных(Поток); // Заголовки ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=" + ИмяСообщения); ЗаписьДанных.ЗаписатьСтроку(""); // Тело ЗаписьДанных.ЗаписатьСтроку(Текст); ЗаписьДанных.Закрыть(); Возврат Поток.ЗакрытьИПолучитьДвоичныеДанные(); КонецФункции // Возвращается HTTP-сообщение в виде ДвоичныеДанные Функция СоздатьСообщение_Изображение(ИмяСообщения, ИмяФайла, Картинка) Поток = Новый ПотокВПамяти(); ЗаписьДанных = Новый ЗаписьДанных(Поток); // Заголовки ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=" + ИмяСообщения + "; filename=" + имяФайла+ "; size=" + "200"); ЗаписьДанных.ЗаписатьСтроку("Content-Type: image/jpeg"); ЗаписьДанных.ЗаписатьСтроку(""); // Тело ЗаписьДанных.Записать(РаботаСФайлами.ДвоичныеДанныеФайла(Картинка)); ЗаписьДанных.Закрыть(); Возврат Поток.ЗакрытьИПолучитьДвоичныеДанные(); КонецФункции Если отправляю без картинок, только ИД номенклатуры, все норм, с картинками, ошибка "unexpected end of multipart data". Код взят с сайта ИТС, который в котором пришлось заменить "==" на "--", иначе сервак не принимал запрос. Добавив картинки, стала ошибка. Выборку картинок показал как пример, нужна помощь с самой ошибкой, получение данных из 1С нормально взято, из примерно удалил часть этого кода специально. |
|||
1
polosov
22.12.20
✎
09:17
|
В очередной раз советую использовать модуль https://github.com/vbondarevsky/1connector
Там отправка файлов в одну строку. |
|||
2
polosov
22.12.20
✎
09:24
|
Вот правильная ссылка https://github.com/vbondarevsky/Connector
|
|||
3
Asmody
22.12.20
✎
09:46
|
(2) Класс! просто и понятно. не то, что в БСП
|
|||
4
Serginio1
22.12.20
✎
09:58
|
(3) Ну да, на .Net еще понятнее
http://catalog.mista.ru/1c/articles/466052/ |
|||
5
Asmody
22.12.20
✎
10:22
|
(4) .Net внутри 1С выглядит как инородное тело.
вот это вообще ужас и кошмар врап=новый COMОбъект("NetObjectToIDispatch45"); HttpClient=Врап.ПолучитьТипИзСборки("System.Net.Http.HttpClient","System.Net.Http.dll"); HttpClientHandler = врап.ПолучитьТип("System.Net.Http.HttpClientHandler"); // Контенты для Post MultipartFormDataContent=Врап.ПолучитьТип("System.Net.Http.MultipartFormDataContent"); StreamContent =Врап.ПолучитьТип("System.Net.Http.StreamContent"); StringContent =Врап.ПолучитьТип("System.Net.Http.StringContent"); ByteArrayContent=Врап.ПолучитьТип("System.Net.Http.ByteArrayContent"); FormUrlEncodedContent =Врап.ПолучитьТип("System.Net.Http.FormUrlEncodedContent"); DecompressionMethods= Врап.ПолучитьТип("System.Net.DecompressionMethods"); ServicePointManager=врап.ПолучитьТип("System.Net.ServicePointManager"); Dictionary=Врап.ПолучитьТип("System.Collections.Generic.Dictionary`2[System.String,System.String]"); StringBuilder=Врап.ПолучитьТип("System.Text.StringBuilder"); String=Врап.ПолучитьТип("System.String"); HttpUtility=Врап.ПолучитьТипИзСборки("System.Web.HttpUtility","System.Web.dll"); |
|||
6
polosov
22.12.20
✎
10:45
|
(4) Тебе бы сделать нормальную обертку, по типу (2). Чтобы инкапсулировать все лишнее.
|
|||
7
Serginio1
22.12.20
✎
10:48
|
(5) Угу как там типы в 1С в 30 и более символов?
Зато все понятно, и таких типов в 1С нет. Да и вынес получение типов как using в отдельный метод, а дальше пиши как и в 1С. Это просто расширение языка без всяких ВК. И куча примеров в том же stackoverflow (6) Так чем это хуже 2 Процедура Multi_PartНажатие(Элемент) // Вставить содержимое обработчика. uriSources =ПолучитьСтрокуЗапроса("http://localhost.fiddler:40320"); //uriSources ="http://localhost:40320"; HttpClient=Врап.ПолучитьТипИзСборки("System.Net.Http.HttpClient","System.Net.Http.dll"); MultipartFormDataContent=Врап.ПолучитьТип("System.Net.Http.MultipartFormDataContent"); Клиент = Врап.СоздатьОбъект(HttpClient); Контент = Врап.СоздатьОбъект(MultipartFormDataContent); Клиент.BaseAddress =Врап.СоздатьОбъект("System.Uri",uriSources); // Вариант отправки Ключ-Значение Значения = Врап.СоздатьОбъект("System.Collections.Generic.Dictionary`2[System.String,System.String]"); Значения.Add("Name", "name"); Значения.Add("id", "id"); // content.Add(new FormUrlEncodedContent(values)); Для каждого КлючЗначение из Значения Цикл Контент.Add(Врап.СоздатьОбъект("System.Net.Http.StringContent",КлючЗначение.Value),КлючЗначение.Key); КонецЦикла; // Вариант отправки двоичных данных из массива Encoding=Врап.ПолучитьТип("System.Text.Encoding"); СтроковыйКонтент =Врап.СоздатьОбъект("System.Net.Http.ByteArrayContent",Encoding.UTF8.GetBytes("Тестовая строка")); ContentDisposition=Врап.СоздатьОбъект("System.Net.Http.Headers.ContentDispositionHeaderValue","form-data"); ContentDisposition.FileName ="ПростоСтрока"; ContentDisposition.Name ="attachment"; СтроковыйКонтент.Headers.ContentDisposition = ContentDisposition; СтроковыйКонтент.Headers.ContentType = Врап.СоздатьОбъект("System.Net.Http.Headers.MediaTypeHeaderValue","text/plain"); Контент.Add(СтроковыйКонтент); // Вариант отправки двоичных данных из файла ИмяФайла ="C:/ТестXML"; ПотокФайла =Врап.ПолучитьТип("System.IO.File").OpenRead(ИмяФайла); ФайловыйКонтент =Врап.СоздатьОбъект("System.Net.Http.StreamContent",ПотокФайла); ContentDisposition=Врап.СоздатьОбъект("System.Net.Http.Headers.ContentDispositionHeaderValue","form-data"); ContentDisposition.FileName = Врап.ПолучитьТип("System.IO.Path").GetFileName(ИмяФайла); ФайловыйКонтент.Headers.ContentDisposition = ContentDisposition; ФайловыйКонтент.Headers.ContentType = Врап.СоздатьОбъект("System.Net.Http.Headers.MediaTypeHeaderValue","application/octet-stream"); Контент.Add(ФайловыйКонтент); // Вариант отправки двоичных данных из файла но более краткий ПотокФайла2 =Врап.ПолучитьТип("System.IO.File").OpenRead(ИмяФайла); ФайловыйКонтент2 =Врап.СоздатьОбъект("System.Net.Http.StreamContent",ПотокФайла2); Контент.Add(ФайловыйКонтент2,"attachment","TestXml"); requestUri = "api/values/SendFiles"; Результат = Клиент.PostAsync(requestUri, Контент).Result; стр = Результат.Content.ReadAsStringAsync().Result; Сообщить(стр); ЗакрытьРесурс(Клиент); ЗакрытьРесурс(Контент); ЗакрытьРесурс(ПотокФайла); // Вот как выглядит отправляемый запрос //POST http://localhost:40320/api/values/SendFiles HTTP/1.1 //Content-Type: multipart/form-data; boundary="9f2d525a-7383-46ab-8fc7-419d73486c02" //Host: localhost:40320 //Content-Length: 811 //Expect: 100-continue //Connection: Keep-Alive //--9f2d525a-7383-46ab-8fc7-419d73486c02 //Content-Type: text/plain; charset=utf-8 //Content-Disposition: form-data; name=Name //name //--9f2d525a-7383-46ab-8fc7-419d73486c02 //Content-Type: text/plain; charset=utf-8 //Content-Disposition: form-data; name=id //id //--9f2d525a-7383-46ab-8fc7-419d73486c02 //Content-Disposition: form-data; filename="=?utf-8?B?0J/RgNC+0YHRgtC+0KHRgtGA0L7QutCw?="; name=attachment //Content-Type: text/plain //Тестовая строка //--9f2d525a-7383-46ab-8fc7-419d73486c02 //Content-Disposition: form-data; filename="=?utf-8?B?0KLQtdGB0YJYTUw=?=" //Content-Type: application/octet-stream //12345 //--9f2d525a-7383-46ab-8fc7-419d73486c02 //Content-Disposition: form-data; name=attachment; filename=TestXml; filename*=utf-8''TestXml //12345 //--9f2d525a-7383-46ab-8fc7-419d73486c02-- КонецПроцедуры |
|||
8
polosov
22.12.20
✎
10:49
|
(7) Ты смеешься?
Посмотри как файлы отсылаются в (2). |
|||
9
Asmody
22.12.20
✎
10:51
|
(8) Ему просто очень нравится нажимать на кнопки. Ну или платят за количество строчек
|
|||
10
Serginio1
22.12.20
✎
10:59
|
(8) Там в примере несколько вариантов отправки файлов, потоков, сток, пар ключей
И завернуть все в 1 метод не проблема. // Вариант отправки двоичных данных из файла но более краткий Процедура ОтправитьФайл(Контент, ИмяФайла) ПотокФайла2 =Врап.ПолучитьТип("System.IO.File").OpenRead(ИмяФайла); ФайловыйКонтент2 =Врап.СоздатьОбъект("System.Net.Http.StreamContent",ПотокФайла2); Контент.Add(ФайловыйКонтент2,"attachment","TestXml"); КонецПроцедуры |
|||
11
Asmody
22.12.20
✎
11:05
|
(10) В 95% случаев не нужно "несколько вариантов бла-бла-бла". И эта задача должна решаться функцией в 1 строку.
Весь бойлерплейт должен быть внутри библиотеки |
|||
12
Serginio1
22.12.20
✎
11:06
|
Я к тому, что на каждый чих писать ВК или Ком компоненту замучаешься.
Можно, для сокращения написать на C# класс с более простым интерфейсом и использовать её без регистрации через NetObjectToIDispatch45 только и всего |
|||
13
polosov
22.12.20
✎
11:19
|
(12) В данном случае все тоже самое делается на 1С. Зачем использовать тогда обертку над C#?
В (2) все реализовано на 1С. |
|||
14
oleg_km
22.12.20
✎
11:19
|
(11) Ну я делаю библиотеку как обработку на 1С. В нее инкапсулирую часть связанного с .NET кода. А так действительно это столько уже бы пришлось написать компонент на шарпе, да еще их распространять на компы нужно. А так одна точка входа в дотнет.
|
|||
15
Serginio1
22.12.20
✎
11:22
|
(13) Не все. На самом деле вариантов отправки там вагон и маленькая тележка.
Ну и не на всех версиях есть поддержка multipart/form-data Кстати как там в 1С с DecompressionMethods.GZip,DecompressionMethods.Deflate Раньше не было |
|||
16
polosov
22.12.20
✎
11:32
|
(15) а ты загляни в модуль из (2). Очень красиво реализовано.
|
|||
17
Serginio1
22.12.20
✎
11:45
|
(16) Искать лень. Кинь код. На .Net это
handler = врап.СоздатьОбъект(HttpClientHandler); handler.AutomaticDecompression=Врап.OR(DecompressionMethods.GZip,DecompressionMethods.Deflate) ; Клиент=Врап.СоздатьОбъект(HttpClient,handler); |
|||
18
polosov
22.12.20
✎
11:49
|
(17) А там все автоматом делается, если в заголовке присутствует указание на сжатие.
|
|||
19
Serginio1
22.12.20
✎
11:51
|
(18) То есть в 1С добавили DecompressionMethods.GZip,DecompressionMethods.Deflate?
|
|||
20
Serginio1
22.12.20
✎
11:54
|
Во всяком случае из недавнего приседают со сторонней библиотекой
чтение - декодирование ответа HTTP POST запроса |
|||
21
polosov
22.12.20
✎
11:58
|
(19) Нет, не добавили. просто человек разобрался как можно сделать типовыми средствами.
|
|||
22
Serginio1
22.12.20
✎
12:02
|
(21) Ну ты код то покажи или ссылку
|
|||
23
polosov
22.12.20
✎
12:10
|
(22)
Функция ПрочитатьGZip(СжатыеДанные) Экспорт РазмерПрефиксаGZip = 10; РазмерПостфиксаGZip = 8; ЧтениеДанных = Новый ЧтениеДанных(СжатыеДанные); ЧтениеДанных.Пропустить(РазмерПрефиксаGZip); РазмерСжатыхДанных = ЧтениеДанных.ИсходныйПоток().Размер() - РазмерПрефиксаGZip - РазмерПостфиксаGZip; ПотокZip = Новый ПотокВПамяти(ZipРазмерLFH() + РазмерСжатыхДанных + ZipРазмерDD() + ZipРазмерCDH() + ZipРазмерEOCD()); ЗаписьДанных = Новый ЗаписьДанных(ПотокZip); ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipLFH()); ЧтениеДанных.КопироватьВ(ЗаписьДанных, РазмерСжатыхДанных); ЗаписьДанных.Закрыть(); ЗаписьДанных = Новый ЗаписьДанных(ПотокZip); CRC32 = ЧтениеДанных.ПрочитатьЦелое32(); РазмерНесжатыхДанных = ЧтениеДанных.ПрочитатьЦелое32(); ЧтениеДанных.Закрыть(); ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipDD(CRC32, РазмерСжатыхДанных, РазмерНесжатыхДанных)); ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipCDH(CRC32, РазмерСжатыхДанных, РазмерНесжатыхДанных)); ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipEOCD(РазмерСжатыхДанных)); ЗаписьДанных.Закрыть(); Возврат ПрочитатьZip(ПотокZip); КонецФункции |
|||
24
Serginio1
22.12.20
✎
12:13
|
(23) Ок. Спасибо. Тут понятно он добавляет данные для чтения Zip.
А для Deflate. |
|||
25
polosov
22.12.20
✎
12:14
|
(24) Для Deflate нет пока. Сделай и оформи PR. Думаю по аналогии можно.
|
|||
26
polosov
22.12.20
✎
12:19
|
(24) Хотя 1С поддерживает Deflate. Возможно и код из (23) справится.
|
|||
27
Serginio1
22.12.20
✎
12:29
|
(26) Ну судя по http://catalog.mista.ru/public/618906/ еще нет.
Ну врукопашную то конечно можно все на 1С переписать и потратить кучу времени или взять уже готовые и приспособить под себя затрачивая минимум времени. Например та же задача для парсинга сайта. http://catalog.mista.ru/public/466196/ |
|||
28
polosov
22.12.20
✎
12:31
|
(27) Но ты же понимаешь, что надо хотя бы базово знать C#
|
|||
29
oleg_km
22.12.20
✎
12:34
|
(28) Ну не вижу в этом проблемы для программиста. Я наоборот после того как 1С подвело меня сначала с ИнтернетПочта, потом с ИнтернетСоединение, вообще перевожу на дотнет все, что доступно на дотнет. У дотнет сколько бета-тестеров, а у 1С?
|
|||
30
polosov
22.12.20
✎
12:41
|
(29) Да конечно не проблема. Можно и картриджи заправлять и чайники чинить.
|
|||
31
polosov
22.12.20
✎
12:52
|
(29) Вот уйдешь ты от своего работодателя, придет другой прог, а ему надо будет поправить чего-нибудь. А у него в резюме не было "Знание 1С+С#"
|
|||
32
Serginio1
22.12.20
✎
12:57
|
(30) А алгоритм Deflate писать на 1С!
Суть использования внешних библиотек это сократить время на программирования и создание эффективного кода. Не хочешь использовать твой выбор. Например если я умею программировать на C# многое в 1С мне значительно проще делать, чем брать чью то непроверенную библиотеку. В том же stackoverflow полно примеров для решения кучи задач. (31) Ну ничего, там разобраться то неделю. И поверь программистов C# в мире значительно больше. Всегда можно найти для решения неких задач. Просто знать 1 язык, это как то не по программистски. А если знаешь несколько языков то понять C# несложно. Вон Гений1С сразу проникся и начал писать на C# |
|||
33
polosov
22.12.20
✎
13:01
|
(32) Да в курсе я этого. Я, например, на в с++ могу. Но при поиске прога 1С гораздо сложнее найти человека со знанием нескольких языков.
|
|||
34
Serginio1
22.12.20
✎
13:11
|
(33) Ну обычно все работают не с отдельными одноэсниками а с франчайзи и прочими. А там обычно есть разные программисты.
В любом случае изучить то .Net не проблема. Что это за программист который не может изучить другой язык? Там глубоких знаний не нужно. Только типы, методы свойства. |
|||
35
polosov
22.12.20
✎
13:14
|
(34) Проблемы нет, для некоторых.
Но ты к примеру сравни оформление кода и документацию в (2) и описание в своих статьях. компетентным везде быть невозможно. |
|||
36
Serginio1
22.12.20
✎
13:26
|
(35) Ну я в статьях продвигаю использование .Net.
В реалиях проще написать dll с классом с нужными методами как в (2) При этом сами классы и типы параметров в методах могут быть не COM совместимы. В большинстве случаев берем примеры со stackOverflow. И кладем эту библиотеку рядом с NetObjetToIDispatch45.dll или в макет и распаковываем в нужное место. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |