Имя: Пароль:
1C
1С v8
Хелп! выгрузка файла POST запросом
, , ,
0 Alex87r
 
16.06.19
12:49
Привет всем!

Никак не получается выгрузить на сайт файл, POST запросом(

Вот мой код. Хочу загрузить на сайт текстовый документ, который на компе "C:\temp.txt"
В ответ приходит ошибка, файл не загружен.

    ТекстДляОтправки = "";
    Boundary = Строка(Новый УникальныйИдентификатор());
    
    ТекстДляОтправки = ТекстДляОтправки + "--"+Boundary + Символы.ПС;
    ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""file""; filename=""file""" + Символы.ПС;
    ТекстДляОтправки = ТекстДляОтправки + "Content-Type: application/x-octet-stream" + Символы.ПС;
    
    ДД = Новый ДвоичныеДанные("C:\temp.txt");
    Данные = Base64Строка(ДД);
        
    ТекстДляОтправки = ТекстДляОтправки + Символы.ПС;
    ТекстДляОтправки = ТекстДляОтправки + Данные + Символы.ПС;
    ТекстДляОтправки = ТекстДляОтправки + "--"+Boundary + Символы.ПС;
    
    Заголовки = Новый Соответствие();
    Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);
    Заголовки.Вставить("Content-Lenght", XMLСтрока(СтрДлина(ТекстДляОтправки)));
    Заголовки.Вставить("authorization", "6q3gCH0mFJWN2qXswQ8WYexfoYPV0KFf");    
    
    HHTPЗапрос = Новый HTTPЗапрос(Подключение.Адрес, Заголовки);
    HHTPЗапрос.УстановитьТелоИзСтроки(ТекстДляОтправки);    
    
    HTTPОтвет = Подключение.HTTP.ОтправитьДляОбработки(HHTPЗапрос);
    ТекстОтвета = HTTPОтвет.ПолучитьТелоКакСтроку();
    Сообщить(ТекстОтвета);

Создаю запрос через программу postman, через нее файл грузится. Т.е. проблема в 1С
Что я делаю не так, подскажите плиз.
1 Юрий Лазаренко
 
16.06.19
12:57
В файле кириллица есть? Может кодировка? Если отправить тестовый файл с одной строкой латинницей, то отправится?
2 Garykom
 
гуру
16.06.19
12:58
Фидлер и сравнивай что через постман а что через 1С уходит
3 Alex87r
 
16.06.19
13:00
(1) В файле число
4 Alex87r
 
16.06.19
13:07
(2) А как в фидлере посмотреть, что я отправил из 1с?
5 Garykom
 
гуру
16.06.19
13:09
(4) https://toster.ru/q/220093

через прокси
6 Юрий Лазаренко
 
16.06.19
13:10
Может там в файле BOM добавляется?
7 Garykom
 
гуру
16.06.19
13:14
Имхо "RFC 7231" это на текущий момент редкостный изврат и пора бы уже на нечто более вменяемое переходить.
На тот же JSON (чистый application/json) вместо кривого текстового протокола с кучей особенностей.
8 dmpl
 
16.06.19
13:32
(0) Content-Length - очепятка.
9 Alex87r
 
16.06.19
14:06
(7) Как через JSON отправить файл?
10 Alex87r
 
16.06.19
14:10
(7) Это я для теста взял блокнот для отправки. Мне нужно выгружать на сайт pdf, картинки и файлы word
11 Garykom
 
гуру
16.06.19
14:12
(9) Сильно проще


HTTPСоединение = Новый HTTPСоединение("1cvpn.ru",1717);
HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса);
HTTPЗапрос.Заголовки.Вставить("Content-type", "application/json");
HTTPЗапрос.УстановитьТелоИзСтроки(""+СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    
Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);  
Сообщить("Код результата: " + Ответ.КодСостояния);
Сообщить("Ответ: " + Ответ.ПолучитьТелоКакСтроку("UTF-8"));
12 Garykom
 
гуру
16.06.19
14:13
(10) Ищи пример как для твоего сайта можно/нужно выгружать правильно.
HTTP протокол он весьма сложный и замороченный, куча глюков бывает и несоответствий протоколу в конкретных реализациях.
13 Alex87r
 
16.06.19
14:19
(12) Из постмана я могу увидеть, как выглядит запрос, который отправляю. Но не на языке 1С.

Мне кажется, что сервер не может расшифровать файл из формата base64.
А как можно отправить из 1С без кодирования в base64?
14 Alex87r
 
16.06.19
14:21
Вот пример кода curl
curl -X POST \
  https:Сервер \
  -H 'authorization: zLaCON1OVO...(оставшаяся часть ключа)' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -F file=@/home/file.doc
15 Garykom
 
гуру
16.06.19
14:22
(14) И как это выглядит в фидлере?
16 Alex87r
 
16.06.19
14:25
В постмане:
  
'https://Сервер' \
  -H 'Accept: */*' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Host: Сервер' \
  -H 'Postman-Token: 2689481c-511c-4d0f-bd2a-46947e9ebaa8,e6b697f6-884b-4738-99f3-23938ea2e6b1' \
  -H 'User-Agent: PostmanRuntime/7.15.0' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'authorization: 6q3gCH0mFJWN2qXswQ8WYexfoYPV0KFf' \
  -H 'cache-control: no-cache,no-cache' \
  -H 'content-length: 209' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -H 'cookie: sails.sid=s%3AkmiGqtMpB3pRu5N4gUGcLzHA-5ZG9gwP.JtLaAZ%2B3J98xTNAXX5JJR2I0coHYAKL5qJoWXwM%2FFWM' \
  -b sails.sid=s%3AkmiGqtMpB3pRu5N4gUGcLzHA-5ZG9gwP.JtLaAZ%2B3J98xTNAXX5JJR2I0coHYAKL5qJoWXwM%2FFWM \
  -F file=@/C:/temp.txt
17 Garykom
 
гуру
16.06.19
14:27
(16) Да нафик этот постман, ты фидлер покажи!
18 dmpl
 
16.06.19
14:28
(13) УстановитьТелоИзДвоичныхДанных()
19 Alex87r
 
16.06.19
14:33
(18) Пробовал, не работает.
20 Alex87r
 
16.06.19
14:34
(17) ща поставлю фидлер, я им не пользуюсь
21 Garykom
 
гуру
16.06.19
14:36
(19) Кстати в 1С "УстановитьТело" по сути же присоединяет к телу запросу данные а не замещает их?

Или есть какие то варианты между разными "УстановитьТелоИзСтроки", "УстановитьТелоИзДвоичныхДанных" и "УстановитьИмяФайлаТела" ?
22 Garykom
 
гуру
16.06.19
14:37
(21) к (18)
23 Garykom
 
гуру
16.06.19
14:39
(21)+ В смысле что будет если дважды вызвать "УстановитьТелоИзДвоичныхДанных" например?
24 Alex87r
 
16.06.19
14:48
В фидлере при отправке из 1С:

--55170dc4-4c22-4ad8-8d72-9870449e5bbb
Content-Disposition: form-data; name="file"; filename="file"
Content-Type: application/x-octet-stream

MTIz
--55170dc4-4c22-4ad8-8d72-9870449e5bbb
25 Alex87r
 
16.06.19
14:48
(23) Он заменяет тело запроса последней строкой
26 Garykom
 
гуру
16.06.19
14:50
(24) А из curl или из postman что в fiddler ?
27 Alex87r
 
16.06.19
14:50
УстановитьТелоИзДвоичныхДанных при отправке запроса просто скопировала в тело запроса текст из блокнота. Т.е. она не добавляет двоичные данные в запрос, а пытается составить запрос из переданных двоичных данных
28 Garykom
 
гуру
16.06.19
14:51
У тебя же задача довольно простая, имея рабочий пример и смотря по сути "текстовый результат" в фидлере, добиться чтобы 1С выдавала такой же текст.

HTTP это текстовый протокол, где все в банальный текст превращается, который и уходит запакованный обычно в gzip
29 Garykom
 
гуру
16.06.19
14:54
(27) Это 1С "--55170dc4-4c22-4ad8-8d72-9870449e5bbb" взяла из заголовка Boundary или сама придумала свой?
30 Alex87r
 
16.06.19
14:54
(28) Я понимаю)
Postman перестал работать с включенным фиддлером)
31 Alex87r
 
16.06.19
14:55
(29) да, это boundary
32 dmpl
 
16.06.19
14:55
А сервер при отправке из 1С что отвечает?
33 Garykom
 
гуру
16.06.19
14:59
(30) В постмане тоже как прокси указал фидлер?
Хотя постман вроде по "Code" текст запроса показывает, фидлер не обязателен
34 Alex87r
 
16.06.19
15:02
(33)
POST Сервер HTTP/1.1
Host: installRequests.api.x-keeper.net
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
authorization: 6q3gCH0mFJWN2qXswQ8WYexfoYPV0KFf
cache-control: no-cache,no-cache
Postman-Token: fe541c6f-d25d-47fb-be57-c5c80c5f885d


Content-Disposition: form-data; name="file"; filename="/C:/temp.txt


------WebKitFormBoundary7MA4YWxkTrZu0gW--
35 dmpl
 
16.06.19
15:07
(34) В теле из 1С Boundary получился --55170dc4-4c22-4ad8-8d72-9870449e5bbb, а в заголовке какой? Судя по коду - без -- в начале.
36 Garykom
 
гуру
16.06.19
15:07
(34) Чтобы на 1С сделать так же надо "УстановитьИмяФайлаТела"
37 Alex87r
 
16.06.19
15:12
(36) Вместо блокнота подставил файл ворд. В фиддлере нечитаемые символы   ࡱ
38 Alex87r
 
16.06.19
15:16
(35) Фиддлер не показывает, что было в заголовке запроса.
В теле запроса вначале Boundary и в конце
39 Alex87r
 
16.06.19
15:16
(35) А в коде я вставляю Boundary:
Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);
40 dmpl
 
16.06.19
15:17
(39) Это в заголовки. А в тело:

  ТекстДляОтправки = ТекстДляОтправки + "--"+Boundary + Символы.ПС;
41 Alex87r
 
16.06.19
15:28
(40)
В теле 2 раза

    ТекстДляОтправки = ТекстДляОтправки + "--"+Boundary + Символы.ПС;
    ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""file""; filename=""file""" + Символы.ПС;
    ТекстДляОтправки = ТекстДляОтправки + "Content-Type: application/x-octet-stream" + Символы.ПС;
    
    ДД = Новый ДвоичныеДанные("C:\Word.doc");
    Данные = Base64Строка(ДД);
        
    ТекстДляОтправки = ТекстДляОтправки + Символы.ПС;
    ТекстДляОтправки = ТекстДляОтправки + Данные + Символы.ПС;
    ТекстДляОтправки = ТекстДляОтправки + "--"+Boundary + Символы.ПС;
42 dmpl
 
16.06.19
15:34
(41) Так какой ответ приходит от сервера в итоге?
43 dmpl
 
16.06.19
15:52
Кстати, последний разделитель должен оканчиваться "--" + Boundary + "--" + Символы.ПС
44 Alex87r
 
16.06.19
15:55
(43) Подправил, но ошибка та же:
Файл не загружен. Проверьте ваш запрос, обратитесь к документации.
45 Alex87r
 
16.06.19
16:10
Ураа у меня получилось!!
Спасибо всем, кто не прошел мимо)

Вот код, может быть пригодится:

    ИмяФайлаОтправки = КаталогВременныхФайлов() + "post.txt";    
    ИмяФайлаДляЗагрузки = "C:\Word.doc";
    
    Сервер = "installRequests.api.x-keeper.net:443";
    Подключение = Новый Структура ("HTTP, ЗаголовокHTTP, Адрес" );    
    Подключение.Адрес = "v1/requests.uploadFile?requestNb=НомерЗаявки&fileCatPreffix=ИДФайла";
    Подключение.Адрес = СтрЗаменить(Подключение.Адрес,"НомерЗаявки", "784-N71");
    Подключение.Адрес = СтрЗаменить(Подключение.Адрес,"ИДФайла", "scan_dover_prikaz_postavshik");    
    
    HTTP = Новый HTTPСоединение(Сервер,,,,,,Новый ЗащищенноеСоединениеOpenSSL);
    
    
    Boundary = Строка(Новый УникальныйИдентификатор());

    //Определяем массив для процедуры ОбъединитьФайлы
    МассивФайловДляОбъединения = Новый Массив;

    //Формируем начальный фрагмент файла POST-запроса
    ИмяФайлаОтправкиНачало = ПолучитьИмяВременногоФайла("txt");
    ФайлОтправкиНачало = Новый ЗаписьТекста(ИмяФайлаОтправкиНачало, КодировкаТекста.ANSI, Символы.ПС, Ложь);
    //Определяем раздел двоичных данных
    ФайлОтправкиНачало.ЗаписатьСтроку("--" + Boundary);
    //Указываем имя файла для передачи
    ФайлОтправкиНачало.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" + ИмяФайлаДляЗагрузки + """");
    //Указываем тип передаваемых данных.
    ФайлОтправкиНачало.ЗаписатьСтроку("Content-Type: application/x-octet-stream");
    ФайлОтправкиНачало.ЗаписатьСтроку("");
    ФайлОтправкиНачало.Закрыть();

    МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиНачало);

    //Копируем файл для загрузки во временный и добавляем в массив файлов для объединения
    ИмяФайлаДляЗагрузкиВременный = ПолучитьИмяВременногоФайла("tmp");
    КопироватьФайл(ИмяФайлаДляЗагрузки, ИмяФайлаДляЗагрузкиВременный);
    МассивФайловДляОбъединения.Добавить(ИмяФайлаДляЗагрузкиВременный);

    //Формируем конечный фрагмент файла POST-запроса
    ИмяФайлаОтправкиКонец = ПолучитьИмяВременногоФайла("txt");
    ФайлОтправкиКонец = Новый ЗаписьТекста(ИмяФайлаОтправкиКонец, КодировкаТекста.ANSI, Символы.ПС, Ложь);

    //Завершение раздела двоичных данных
    ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary);

    ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary + "--");
    ФайлОтправкиКонец.Закрыть();

    МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиКонец);

    //Теперь сформированные фрагменты сообщения для сервера объединяем в один файл POST-запроса
    ОбъединитьФайлы(МассивФайловДляОбъединения, ИмяФайлаОтправки);     
    Заголовки = Новый Соответствие();
    Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);

    Заголовки.Вставить("authorization", "6q3gCH0mFJWN2qXswQ8WYexfoYPV0KFf");    
    
    HHTPЗапрос = Новый HTTPЗапрос(Подключение.Адрес, Заголовки);
    HHTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);    

    HTTPОтвет = HTTP.ОтправитьДляОбработки(HHTPЗапрос);
    ТекстОтвета = HTTPОтвет.ПолучитьТелоКакСтроку();
    Сообщить(ТекстОтвета);
46 Garykom
 
гуру
16.06.19
16:15
(45) "x-keeper.net" - гм знакомая штука вот J2ME тут http://m.x-keeper.net/ это я когда то давным-давно ваял ))
47 Alex87r
 
16.06.19
16:30
(46) Прикольно) А я делаю интеграцию через их API
48 zwolf
 
16.06.19
16:31
(46) > знакомая штука
Отлично! А подскажи, пожалуйста, что там можно сделать со случайно найденном в интернете токеном авторизации? (:
49 Garykom
 
гуру
16.06.19
16:38
(48) Не в курсе, когда я писал там весь обмен был через SMS сообщения и запросы к серверу.
Но думаю можно машину заглушить или заставить сделать сигналку обратный звонок на твой номер для прослушивания что там в салоне ))
50 Alex87r
 
16.06.19
16:44
(48) Ничего)) это тестовый токен