|
Отправка файла на Яндекс Диск | ☑ | ||
---|---|---|---|---|
0
yurii-syrkin
22.08.19
✎
14:29
|
Здравствуйте. Появилась задача отправить большой файл на почту. Обычной отправкой сделать это не получается, файл слишком большой. Решили выгружать его на яндекс диск и в письме писать ссылку на скачивание файла с яндекс диска. Копирую следующим кодом:
Путь1 = ИмяФайла; Файл = Новый Файл(Путь1); ИмяФайла = Файл.Имя; Путь2 = "https://" + Логин + ":" + Пароль + "@webdav.yandex.ru/" + ИмяФайла; КопироватьФайл(Путь1, Путь2); Копируется нормально, потом в яндекс диске этот файл вижу. Но не пойму как получить ссылку на скачивание файла. Мне же нужно именно программно получить эту ссылку, а не заходить потом на яндекс диск и интерфейсными кнопками её копировать. Вот такая вот проблема. Спасибо. |
|||
1
dka80
22.08.19
✎
14:32
|
||||
2
Йохохо
22.08.19
✎
14:43
|
||||
3
yurii-syrkin
22.08.19
✎
15:01
|
Чёт не могу это к 1С применить. Только не бейте сильно)
|
|||
4
yurii-syrkin
22.08.19
✎
17:04
|
Приложение зарегистрировал, токен получил. Как писать код в 1С не знаю. Ну помогите, что вам сложно что ли
|
|||
5
dezss
22.08.19
✎
17:07
|
(4) HTTPСоединение и HTTPЗапрос используй.
Описание есть в СП. |
|||
6
yurii-syrkin
22.08.19
✎
17:11
|
Соединение = Новый HTTPСоединение("cloud-api.yandex.net", ,"Логин", "Пароль");
ИмяФайла_ = СтрЗаменить(ИмяФайла, "\", "%"); Токен = "AgAAAAA3EqYMAAXWQ1YuubMsO0MVvWA-nd5nVPg"; ТекстЗапроса = "https://cloud-api.yandex.net/v1/disk/resources/upload? path=" + ИмяФайла_ + " & overwrite=true"; httpЗапрос = Новый HTTPЗапрос(ТекстЗапроса); Ответ = Соединение.ВызватьHTTPМетод("GET", httpЗапрос); Выдаёт ошибку Ответ = Соединение.ВызватьHTTPМетод("GET", httpЗапрос); по причине: Ошибка работы с Интернет: Не могу установить соединение |
|||
7
dka80
22.08.19
✎
17:11
|
Ресурс = "bot" + Объект.Токен + "/sendMessage?chat_id=" + СтрЗаменить(Формат(chat_id, "ЧДЦ=; ЧС=; ЧРГ=."), ".", "") + "&text=" + ТекстОшибки;
Соединение = Новый HTTPСоединение(Объект.Сервер,443,,,,,Новый ЗащищенноеСоединениеOpenSSL()); Запрос = Новый HTTPЗапрос(Ресурс); Ответ = Соединение.Получить(Запрос); только в переменную ресурс правильно подставь значение из (2) |
|||
8
dezss
22.08.19
✎
17:14
|
(6)Соединение = Новый HTTPСоединение("cloud-api.yandex.net", ,"Логин", "Пароль",,,Новый ЗащищенноеСоединениеOpenSSL);
ТекстЗапроса = "/v1/disk/resources/upload? path=" + ИмяФайла_ + " & overwrite=true"; И в httpЗапрос = Новый HTTPЗапрос(ТекстЗапроса); установи заголовки, если они нужны. |
|||
9
dezss
22.08.19
✎
17:15
|
(8) + Лишние пробелы убирай нафиг
ТекстЗапроса = "/v1/disk/resources/upload?path=" + ИмяФайла_ + "&overwrite=true"; |
|||
10
dezss
22.08.19
✎
17:18
|
+ потом сразу делаешь PUT, по полученному ответу из доки (аналогичным образом, только httpСоединение и httpЗапрос переделай на другой путь, на тот, что придет в ответе). Ну а потом publish аналогичным образом.
|
|||
11
yurii-syrkin
22.08.19
✎
17:21
|
Пока не врубился куда токен вставлять. В документации в формате запросов смотрю он не участвует. Я так понял это
"Ресурс = "bot" + Объект.Токен + "/sendMessage?chat_id=" + СтрЗаменить(Формат(chat_id, "ЧДЦ=; ЧС=; ЧРГ=."), ".", "") + "&text=" + ТекстОшибки;" вообще из другой темы? |
|||
12
dezss
22.08.19
✎
17:22
|
(11) Да, это обращение к боту телеграмма.
Токен, скорей всего, нужен в заголовках. Сча доку гляну. |
|||
13
dezss
22.08.19
✎
17:25
|
(12) +
Полученный токен следует передавать в заголовке Authorization при каждом вызове API Диска, указывая тип токена перед его значением. Пример такого заголовка: Authorization: OAuth 0c4181a7c2cf4521964a72ff57a34a07 И не забывай: Корректные заголовки Accept и Content-Type: API Диска поддерживает только один MIME-тип, application/json. Любое другое значение приведет к ошибке формата данных. Так что добавляй еще один заголовок Content-Type: application/json |
|||
14
dezss
22.08.19
✎
17:27
|
Предвосхищая вопрос о том, куда и как пихать эти заголовки, а то через 3 минуты ухожу домой)
Заголовки = Новый Соответсвие; Заголовки.Вставить("Authorization","OAuth 0c4181a7c2cf4521964a72ff57a34a07"); Заголовки.Вставить("Content-Type","application/json"); httpЗапрос = Новый HTTPЗапрос(ТекстЗапроса,Заголовки); |
|||
15
yurii-syrkin
22.08.19
✎
17:45
|
Понимаю, что туплю, но всё же. Пишу следующий код
Соединение = Новый HTTPСоединение("cloud-api.yandex.net", ,"Логин", "Пароль"); ИмяФайла_ = СтрЗаменить(ИмяФайла, "\", "%"); Токен = "Это_токен_29020цдаопыавщп2952"; ТекстЗапроса = "https://cloud-api.yandex.net/v1/disk/resources/upload?path=" + ИмяФайла_ + "&overwrite=true"; Заголовки = Новый Соответствие; Заголовки.Вставить("Authorization","OAuth " + Токен); Заголовки.Вставить("Content-Type","application/json"); httpЗапрос = Новый HTTPЗапрос(ТекстЗапроса, Заголовки); Ответ = Соединение.Получить(httpЗапрос); На последней строке висит секунд 30 и вылетает с ошибкой Ошибка при вызове метода контекста (Получить) Ответ = Соединение.Получить(httpЗапрос); по причине: Ошибка работы с Интернет: Не могу установить соединение |
|||
16
gSha
22.08.19
✎
17:53
|
Процедура Тест()
Host = "https://webdav.yandex.ru:443/"; Cat = "Test"; Если спзжКаталог(Cat) = "" тогда xhr = Новый COMОбъект("Microsoft.XMLHTTP"); // 'CreateObject("WinHttp.WinHttpRequest.5.1") xhr.Open("MKCOL", urlencode(Host + Cat), False); xhr.setRequestHeader("Authorization", "Basic " + Token()); //xhr.setRequestHeader("Authorization", "Basic " + Токен); xhr.send(); Если xhr.Status <> 201 тогда Сообщить(Строка(xhr.StatusText)+" "+Строка(xhr.Status)); Возврат; КонецЕсли; КонецЕсли; FileN = "ReadMeTradeWareEPF.txt"; FileN = СтрЗаменить(FileN, "/", "_"); avFiles = "C:\Обрезание\ReadMeTradeWareEPF.txt"; UploadFile(FileN, avFiles, Cat); hlink = Public_url(FileN, Cat); Если hlink = "" Then Сообщить("ВНИМАНИЕ! НЕТ ССЫЛКИ"); Иначе Сообщить(hlink); КонецЕсли; КонецПроцедуры Функция спзжКаталог(RemotePath) Перем sReq; Перем FileContents; Перем FileName; Host = "https://webdav.yandex.ru:443/"; Catalog = ""; sReq = ""; sReq = sReq + "<propfind xmlns='DAV:'> "; sReq = sReq + "<allprop/>"; sReq = sReq + "</propfind>"; Catalog = ""; RemotePath = ?(RemotePath <> "", RemotePath + "/", ""); xhr = Новый COMОбъект("Microsoft.XMLHTTP"); //'CreateObject("WinHttp.WinHttpRequest.5.1") xhr.Open("PROPFIND", urlencode(Host + RemotePath), False); xhr.setRequestHeader("Depth", "0"); xhr.setRequestHeader("Authorization", "Basic " + Token()); xhr.setRequestHeader("Content-Length", "158"); xhr.send(sReq); oResponseDoc = xhr.responseXML(); oNodeList = oResponseDoc.getElementsByTagName("d:status"); Для Каждого elem из oNodeList цикл Catalog = elem.Text; КонецЦикла; Возврат Catalog; КонецФункции &НаКлиенте Function Token() Логин = "указать"; Пароль = "указать"; //Пишем его в файл, чтобы потом закодировать ИмяФайлаТокен = ПолучитьИмяВременногоФайла(); ФайлТокен = Новый ЗаписьТекста(ИмяФайлаТокен,"windows-1251"); ФайлТокен.Записать(Логин+":"+Пароль); ФайлТокен.Закрыть(); // Кодируем пароль в Base64 ДвоичныйТокен = Новый ДвоичныеДанные(ИмяФайлаТокен); Токен = Base64Строка(ДвоичныйТокен); //и удаляем временный файл УдалитьФайлы(ИмяФайлаТокен); Возврат Токен; КонецФункции &НаСервере Функция urlencode(url) // к великому сожалению с русскими буквами не разобрался Возврат url; КонецФункции |
|||
17
gSha
22.08.19
✎
17:57
|
НаКлиенте
Функция Public_url(LocalFilePath, RemotePath) Перем sReq; Перем FileContents , FileName; sReq = ""; Public_url = ""; Host = "https://webdav.yandex.ru:443/"; sReq = sReq + "<propertyupdate xmlns='DAV:'> "; sReq = sReq + "<set><prop>"; sReq = sReq + "<public_url xmlns='urn:yandex:disk:meta'>true</public_url>"; sReq = sReq + "</prop></set>" ; sReq = sReq + "</propertyupdate>" ; FileName = LocalFilePath ; //'Replace(FileName, "/", "_") xhr = Новый COMОбъект("Microsoft.XMLHTTP"); // 'CreateObject("WinHttp.WinHttpRequest.5.1") xhr.Open("PROPPATCH", urlencode(Host + RemotePath + FileName), False); xhr.setRequestHeader("Host", "webdav.yandex.ru"); xhr.setRequestHeader("Authorization", "Basic " + Token()); xhr.setRequestHeader("Content-Length", "158"); xhr.setRequestHeader("User-Agent", "my_application/0.0.1"); xhr.send (sReq); Если xhr.Status <> 207 тогда Сообщить(Строка(xhr.StatusText)+" "+Строка(xhr.Status)); Иначе oResponseDoc = xhr.responseXML(); oNodeList = oResponseDoc.getElementsByTagName("d:prop"); // 'd:response Для Каждого elem из oNodeList цикл Public_url = elem.Text КонецЦикла; КонецЕсли; Возврат Public_url; КонецФункции |
|||
18
big
23.08.19
✎
05:45
|
Вот здесь один хороший человек всё сделал и в открытый доступ выложил. )
https://github.com/vpozdnyakov/YandexDiskExchangeXML |
|||
19
dezss
23.08.19
✎
08:28
|
(15) А вот это ты не заметил?
Соединение = Новый HTTPСоединение("cloud-api.yandex.net", ,"Логин", "Пароль",,,Новый ЗащищенноеСоединениеOpenSSL); Обращаю внимание! Новый ЗащищенноеСоединениеOpenSSL!!! Там обмен идет по https,а не http. Поэтому нужно именно защищенное соединение. И, кстати, не факт что нужны логин и пароль. Так что попробуй и с ними, и без них |
|||
20
dezss
23.08.19
✎
08:33
|
(16) (17) Вот не понимаю, зачем пользоваться чем-то сторонним, если можно использовать стандартный функционал 1С?
|
|||
21
dezss
23.08.19
✎
08:40
|
Судя по (18) логин и пароль не нужны.
Только токен. |
|||
22
yurii-syrkin
23.08.19
✎
15:17
|
Ещё раз здравствуйте. Пишу вот такой код
Соединение = Новый HTTPСоединение("cloud-api.yandex.net",,,,,,Новый ЗащищенноеСоединениеOpenSSL); КодID = "27db1ea35468689efe016ae754683b"; файл = "C:/date.xml"; ТекстЗапроса = "/v1/disk/resources/upload?path=" + файл; Заголовки = Новый Соответствие; Заголовки.Вставить("Content-Type","application/json"); Заголовки.Вставить("Authorization","OAuth AgAAAAввAXWQ1YuubMsO0MVvWA-nd5565Pg"); httpЗапрос = Новый HTTPЗапрос(ТекстЗапроса, Заголовки); Ответ = Соединение.Получить(httpЗапрос); В ответе ошибка 400 |
|||
23
eklmn
гуру
23.08.19
✎
15:53
|
(22) что такое файл?
в каком виде покажи |
|||
24
ptiz
23.08.19
✎
16:07
|
(22) ТекстЗапроса = "/v1/disk/resources/upload";
СтруктураЗапроса = Новый Структура; СтруктураЗапроса.Вставить("path", файл); ... httpЗапрос.УстановитьТелоИзСтроки(ЗаписатьJSONСтроку(СтруктураЗапроса)); ну и: Функция ЗаписатьJSONСтроку(Структура) Экспорт ЗаписьJSON = Новый ЗаписьJSON; ЗаписьJSON.УстановитьСтроку(); ЗаписатьJSON(ЗаписьJSON, Структура); Стр = ЗаписьJSON.Закрыть(); Возврат Стр; КонецФункции // ЗаписатьJSONСтроку() |
|||
25
hhhh
23.08.19
✎
16:07
|
(22) почему C:/date.xml ?? Это же дикость, помещать файл в корень диска С.
|
|||
26
dezss
23.08.19
✎
16:09
|
(22) ? path=<путь, по которому следует загрузить файл>
Это путь на яндекс-диске, а не на локальном компе. Этот метод вернет тебе ссылку, куда надо будет следующим методом грузить сам файл |
|||
27
ptiz
23.08.19
✎
16:11
|
+(24) ой, у тебя ж get
тогда вообще УстановитьТелоИзСтроки() не надо |
|||
28
dezss
23.08.19
✎
16:17
|
(27) Он делает как надо, только в файл запихал не то, что нужно)
|
|||
29
gSha
23.08.19
✎
16:52
|
(19) потому что для меня это все набор бесмысленного текста. Просто в моем случае файл загружается. А в вашем вы так до финала не дошли еще.
|
|||
30
dezss
23.08.19
✎
16:59
|
(29) Это ответ на (20), я так понимаю&
В моем случае все работает. Это у ТС никак не получается. |
|||
31
yurii-syrkin
23.08.19
✎
17:16
|
Итак, коллеги разобрался. Вот код
Функция РазделитьURL(Знач URL) ИмяСервера = ""; Путь = ""; Протокол = ""; Порт = 443; URL = СокрЛП(URL); Если Лев(URL, 7) = "http://" Тогда URL = Прав(URL, СтрДлина(URL) - 7); Протокол = "http"; ИначеЕсли Лев(URL, 8) = "https://" Тогда URL = Прав(URL, СтрДлина(URL) - 8); Протокол = "https"; КонецЕсли; Индекс = СтрНайти(URL, "/"); Если Индекс Тогда ИмяСервера = Лев(URL, Индекс - 1); Путь = Сред(URL, Индекс); КонецЕсли; Индекс = СтрНайти(ИмяСервера, ":"); Если Индекс Тогда Порт = Число(Сред(ИмяСервера, Индекс + 1)); ИмяСервера = Лев(ИмяСервера, Индекс - 1); КонецЕсли; Результат = Новый Структура; Результат.Вставить("ИмяСервера", ИмяСервера); Результат.Вставить("Путь", Путь); Результат.Вставить("Протокол", Протокол); Результат.Вставить("Порт", Порт); Возврат Результат; КонецФункции Функция ПолучитьСсылкуНаСкачивание(ИмяФайла) // 1. Получение ссылки для размещения файла на яндекс диске Файл = Новый Файл(ИмяФайла); ПутьКФайлуНаЯндексДиске = Файл.Имя; ИмяСервера = "cloud-api.yandex.net"; ОтносительныйURL = "/v1/disk/resources/upload?path=" + ПутьКФайлуНаЯндексДиске + "&overwrite=" + XMLСтрока(Истина); Заголовки = Новый Соответствие; Заголовки.Вставить("Content-Type","application/json"); Заголовки.Вставить("Authorization","OAuth ылдоарплыфарпжцфыйолващй"); HttpЗапрос = Новый HTTPЗапрос(ОтносительныйURL, Заголовки); HttpСоединение = Новый HTTPСоединение(ИмяСервера, 443,,,,, Новый ЗащищенноеСоединениеOpenSSL); HttpОтвет = HttpСоединение.Получить(HTTPЗапрос); ТелоОтвета = HttpОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8); Чтение = Новый ЧтениеJSON; Чтение.УстановитьСтроку(ТелоОтвета); Ответ = ФабрикаXDTO.ПрочитатьJSON(Чтение); // 2. Загрузка файла на яндекс диск СтруктураURL = РазделитьURL(Ответ.href); HttpСоединение = Новый HTTPСоединение(СтруктураURL.ИмяСервера, СтруктураURL.Порт,,,,, Новый ЗащищенноеСоединениеOpenSSL); HttpЗапрос = Новый HTTPЗапрос(СтруктураURL.Путь, Заголовки); HttpЗапрос.УстановитьТелоИзДвоичныхДанных(новый ДвоичныеДанные(ИмяФайла)); HttpОтвет = HttpСоединение.Записать(HTTPЗапрос); ТелоОтвета = HttpОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8); Если ТелоОтвета <> "" Тогда Чтение = Новый ЧтениеJSON; Чтение.УстановитьСтроку(ТелоОтвета); Ответ = ФабрикаXDTO.ПрочитатьJSON(Чтение); КонецЕсли; //ПутьКФайлуНаЯндексДиске = HttpОтвет.Заголовки.Получить("Location"); // 3. получение публичной ссылки ТекстЗапроса = "/v1/disk/resources/publish?path=" + ПутьКФайлуНаЯндексДиске; HttpЗапрос = Новый HTTPЗапрос(ТекстЗапроса, Заголовки); HttpСоединение = Новый HTTPСоединение(ИмяСервера, 443,,,,, Новый ЗащищенноеСоединениеOpenSSL); HttpОтвет = HttpСоединение.Записать(HTTPЗапрос); ТелоОтвета = HttpОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8); Чтение = Новый ЧтениеJSON; Чтение.УстановитьСтроку(ТелоОтвета); Ответ = ФабрикаXDTO.ПрочитатьJSON(Чтение); // 4. Получение метаданных файла ТекстЗапроса = "/v1/disk/resources?path=" + ПутьКФайлуНаЯндексДиске; HttpЗапрос = Новый HTTPЗапрос(ТекстЗапроса, Заголовки); HttpОтвет = HttpСоединение.Получить(HTTPЗапрос); ТелоОтвета = HttpОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8); Чтение = Новый ЧтениеJSON; Чтение.УстановитьСтроку(ТелоОтвета); Ответ = ФабрикаXDTO.ПрочитатьJSON(Чтение); Возврат Ответ.public_url; КонецФункции public_url это и есть ссылка для скачивания Всем спасибо! |
|||
32
gSha
23.08.19
✎
17:17
|
ну отлично ..
теперь я вставлю и у мекня тоже будет родными средствами 1с) |
|||
33
gSha
23.08.19
✎
17:18
|
единственное не еще подкаталоги надо создавать в процессе
|
|||
34
dezss
26.08.19
✎
09:09
|
(31) Уточнение:
1. Новый ЗащищенноеСоединениеOpenSSL нужно только если https, иначе тужа Неопределено подставляй. 2. Вместо Ответ = ФабрикаXDTO.ПрочитатьJSON(Чтение), можно использовать просто ПрочитатьJSON(Чтение). Что будет быстрей, не проверял. 3. HttpОтвет = HttpСоединение.Получить(HTTPЗапрос) лучше обернуть в Попытку-Исключение, а то могут там ошибки выскакивать (если не смог разрешить имя сервера или не удалось установить защищенное подключение). 4. Порт указывать не нужно. 443-й будет использоваться если установлено Новый ЗащищенноеСоединениеOpenSSL, иначе 80-й (вроде). 5. Так же в HttpОтвет нужно проверять КодСостояния, а то может что-то не так с сервером и он вернул не 2хх. Т.е. в идеальном случае работать все будет, но вот в случае каких-то нештатных ситуация или изменений у яндекса могут возникать ошибки. А так молодец, сделал довольно неплохо. :) |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |