уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Итак, продолжим тему работы с сервисом Яндекс.Диск в Delphi. Кто не знает или уже забыл — ранее я уже писал про работу с API этого сервиса и даже выложил небольшой исходник, реализующий основные методы WebDAV с использованием моей любимой библиотеки Synapse. В прошлый раз я остановился на том, что реализовал в отдельном классе TWebDAVSend методы протокола WebDAV такие как PROPFIND, MKCOL и т.д. Сегодня мы с Вами немного расширим возможности этого класса и сделаем возможность скачивать и загружать файла в аккаунт Яндекс.Диска.

Открываем документацию API Яндекс.Диска, проект Delphi и приступаем к работе.

Чтение списка ресурсов

В начале немного разберемся с тем, что присылается нам в ответе на запрос методом PROPFIND. После выполнения PROPFIND сервер нам возвращает XML-файл, содержащий свойства ресурсов. При этом каждый узел с описанием свойств ресурса может содержать следующие дочерние элементы:

  • d:href — путь к ресурсу
  • d:propstat— содержит код статуса выполнения операции и набор индивидуальных свойств ресурса
    • d:status — код статуса выполнения операции. Например, если мы будем использовать метод PROPPATCH (редактирование свойств ресурса), то этот узел поможет нам узнать прошла ли операция успешно или нет.
    • d:prop— коллекция свойств ресурса
      • d:creationdate — дата создания ресурса в UTC
      • d:displayname — имя ресурса, которое используется для отображения в интерфейсе пользователя
      • d:getcontentlength — размер ресурса в байтах. Соответственно, для коллекций это свойство всегда равно 0.
      • d:getlastmodified — дата последнего изменения ресурса (по формату отличается от даты, представленной в d:creationdate)
      • d:resourcetype — признак того, что ресурс является коллекцией. Если у этого узла имеется дочерний пустой узел d:collection,  то ресурс является коллекцией, иначе — файлом.

Теперь допишем наш проект и сделаем так, чтобы в интерфейсе программы отображались все файлы и коллекции запрошенные методом PROPFIND. Интерфейс программы у меня теперь стал таким:

Интерфейс программы

В ListView будем выводить информацию по ресурсам. В качестве заготовки будущих классов для работы с API Яндекс.Диска я создал следующие классы:

класс, хранящий информацию по ресурсу:

type
  TWDResource = class
  private
    FHref         : string;
    FStatusCode   : integer;
    FContentLength: int64;
    FCreationDate : TDateTime;
    FLastmodified : TDateTime;
    FDisplayName  : string;
    FContentType  : string;
    FCollection   : Boolean;
  public
    property StatusCode   : integer read FStatusCode;
    property ContentLength: int64 read FContentLength;
    property CreationDate : TDateTime read FCreationDate;
    property Lastmodified : TDateTime read FLastmodified;
    property DisplayName  : string read FDisplayName;
    property ContentType  : string read FContentType;
    property Href: string read FHref;
    property Collection   : Boolean read FCollection;
end;

Потом в этот класс можно будет добавить методы для редактирования свойств и т.д. Пока же он у нас будет выполнять одну простую роль — хранить информацию по одному ресурсу.
Следующий класс — коллекция (список ресурсов) аккаунта:

TWDResourceList = class(TList)
public
  constructor Create;
  destructor Destroy;override;
  procedure Clear;
end;

Здесь, вроде бы, тоже ничего сверхсложного нету — класс хранит список всех запрошенных ранее ресурсов и, по необходимости — чистит список.
Теперь приступим к работе с API и напишем обработчик OnClick кнопки «Выполнить» следующим образом:

procedure TForm5.Button1Click(Sender: TObject);
 
procedure ParseResources(const AXMLStr: string);
var XMLDoc: IXMLDocument;
    ResponseNode,ChildNode,PropNodeChild, PropertyNode: IXMLNode;
     s, su,Value: string;
begin
  XMLDoc:=TXMLDocument.Create(nil);
  try
    XMLDoc.LoadFromXML(AXMLStr);
    if not XMLDoc.IsEmptyDoc then
      begin
        ResponseNode:=XMLDoc.DocumentElement.ChildNodes.First;
        while Assigned(ResponseNode) do
          begin
            Resources.Add(TWDResource.Create);
            ChildNode:=ResponseNode.ChildNodes.First;
            while Assigned(ChildNode) do
              begin
                if ChildNode.NodeName='d:href' then
                   Resources.Last.FHref:=ChildNode.Text
                else
                  if ChildNode.NodeName='d:propstat' then
                    begin
                      PropNodeChild:=ChildNode.ChildNodes.First;
                      while Assigned(PropNodeChild) do
                        begin
                          if PropNodeChild.NodeName='d:status' then
                            begin
                              Value:=PropNodeChild.Text;
                              s := Trim(SeparateRight(Value, ' '));
                              su := Trim(SeparateLeft(s, ' '));
                              Resources.Last.FStatusCode:=StrToIntDef(su, 0);
                            end
                          else
                            if PropNodeChild.NodeName='d:prop' then
                              begin
                                PropertyNode:=PropNodeChild.ChildNodes.First;
                                while Assigned(PropertyNode) do
                                  begin
                                    if PropertyNode.NodeName='d:creationdate' then
                                      Resources.Last.FCreationDate:=UTCToSystemTime(ISODateTime2UTC(PropertyNode.Text))
                                    else
                                      if PropertyNode.NodeName='d:displayname' then
                                        Resources.Last.FDisplayName:=Utf8ToAnsi(PropertyNode.Text)
                                      else
                                        if PropertyNode.NodeName='d:getcontentlength' then
                                          Resources.Last.FContentLength:=PropertyNode.NodeValue
                                        else
                                          if PropertyNode.NodeName='d:getlastmodified' then
                                            Resources.Last.FLastmodified:=DecodeRfcDateTime(PropertyNode.Text)
                                          else
                                            if PropertyNode.NodeName='d:resourcetype' then
                                              Resources.Last.FCollection:=PropertyNode.ChildNodes.Count>0;
                                    PropertyNode:=PropertyNode.NextSibling;
                                  end;
                              end;
                          PropNodeChild:=PropNodeChild.NextSibling;
                        end;
                    end;
                ChildNode:=ChildNode.NextSibling;
              end;
            ResponseNode:=ResponseNode.NextSibling;
          end;
      end;
  finally
    XMLDoc:=nil;
  end;
end;
 
var Str: string;
  I: Integer;
begin
  WebDAV.Login := Edit1.Text;
  WebDAV.Password := Edit2.Text;
  Resources.Clear;
  Str:=WebDAV.PROPFIND(1, InputBox('Ресурс', 'Ресурс', ''));
  if Length(Trim(Str))>0 then
    begin
      ParseResources(Str);
      for I := 0 to Resources.Count-1 do
        begin
          with ListView1.Items.Add do
            begin
              Caption:=Resources[i].DisplayName;
              SubItems.Add(Resources[i].Href);
              SubItems.Add(DateTimeToStr(Resources[i].CreationDate));
              SubItems.Add(DateTimeToStr(Resources[i].Lastmodified));
              SubItems.Add(IntToStr(Resources[i].ContentLength));
              if Resources[i].Collection then
                SubItems.Add('yes')
              else
                SubItems.Add('no');
              SubItems.Add(IntToStr(Resources[i].StatusCode))
            end;
        end;
 
    end;
end;

Выглядит довольно жутенько, поэтому рассмотрим этот метод по частям. Начнем с основного кода процедуры. Вначале мы записываем логин/пароль пользователя и запрашиваем методом PROPFIND сведения по ресурсу, который пользователь задаст в InputBox:

WebDAV.Login := Edit1.Text;
  WebDAV.Password := Edit2.Text;
  Resources.Clear;
  Str:=WebDAV.PROPFIND(1, InputBox('Ресурс', 'Ресурс', ''));

Если запрос прошел успешно и сервер вернул нам ответ, то выполняется вложенная процедура ParseResources, которая и разбирает XML-документ. Сама процедура хоть и выглядит немного громоздко, но является довольно простой — проходит последовательно по всем узлам XML и считывает информацию по ресурсам. Если Вам трудно разобраться с тем, что делает ParseResources, то ниже я представил Вам листинг этой процедуры с некоторыми комментариями к коду:

procedure ParseResources(const AXMLStr: string);
var XMLDoc: IXMLDocument;
    ResponseNode,ChildNode,PropNodeChild, PropertyNode: IXMLNode;
     s, su,Value: string;
begin
  XMLDoc:=TXMLDocument.Create(nil);
  try
    XMLDoc.LoadFromXML(AXMLStr);
    if not XMLDoc.IsEmptyDoc then
      begin
        //выбираем первый узел d:response
        ResponseNode:=XMLDoc.DocumentElement.ChildNodes.First;
        while Assigned(ResponseNode) do
          begin
            //создаем запись нового ресурса в списке
            Resources.Add(TWDResource.Create);
            //проходим по дочерним узлам d:response
            ChildNode:=ResponseNode.ChildNodes.First;
            while Assigned(ChildNode) do
              begin
                if ChildNode.NodeName='d:href' then
                   Resources.Last.FHref:=ChildNode.Text
                else
                  //нашли узел со свойствами ресурса
                  if ChildNode.NodeName='d:propstat' then
                    begin
                      //выбираем первый дочерний узел, обычно - это d:status
                      PropNodeChild:=ChildNode.ChildNodes.First;
                      while Assigned(PropNodeChild) do
                        begin
                          //считываем код статуса
                          if PropNodeChild.NodeName='d:status' then
                            begin
                              Value:=PropNodeChild.Text;
                              s := Trim(SeparateRight(Value, ' '));
                              su := Trim(SeparateLeft(s, ' '));
                              Resources.Last.FStatusCode:=StrToIntDef(su, 0);
                            end
                          else
                            //нашли узел d:prop - проходимся по его дочерним узлам
                            if PropNodeChild.NodeName='d:prop' then
                              begin
                                PropertyNode:=PropNodeChild.ChildNodes.First;
                                while Assigned(PropertyNode) do
                                  begin
                                    if PropertyNode.NodeName='d:creationdate' then
                                      Resources.Last.FCreationDate:=UTCToSystemTime(ISODateTime2UTC(PropertyNode.Text))
                                    else
                                      if PropertyNode.NodeName='d:displayname' then
                                        Resources.Last.FDisplayName:=Utf8ToAnsi(PropertyNode.Text)
                                      else
                                        if PropertyNode.NodeName='d:getcontentlength' then
                                          Resources.Last.FContentLength:=PropertyNode.NodeValue
                                        else
                                          if PropertyNode.NodeName='d:getlastmodified' then
                                            Resources.Last.FLastmodified:=DecodeRfcDateTime(PropertyNode.Text)
                                          else
                                            if PropertyNode.NodeName='d:resourcetype' then
                                              Resources.Last.FCollection:=PropertyNode.ChildNodes.Count>0;
                                    //выбираем следующий дочерний узел у d:prop
                                    PropertyNode:=PropertyNode.NextSibling;
                                  end;
                              end;
                          //выбираем следующий дочерний узел у d:propstat
                          PropNodeChild:=PropNodeChild.NextSibling;
                        end;
                    end;
                //выбираем следующий дочерний узел у d:response
                ChildNode:=ChildNode.NextSibling;
              end;
            //выбираем следующий узел d:response
            ResponseNode:=ResponseNode.NextSibling;
          end;
      end;
  finally
    XMLDoc:=nil;
  end;
end;

После того, как список ресурсов заполнен снова возвращаемся в основной код процедуры OnClick и заполняем ListView данными:

for I := 0 to Resources.Count-1 do
   begin
      with ListView1.Items.Add do
         begin
            Caption:=Resources[i].DisplayName;
            SubItems.Add(Resources[i].Href);
            SubItems.Add(DateTimeToStr(Resources[i].CreationDate));
            SubItems.Add(DateTimeToStr(Resources[i].Lastmodified));
            SubItems.Add(IntToStr(Resources[i].ContentLength));
            if Resources[i].Collection then
              SubItems.Add('yes')
            else
              SubItems.Add('no');
            SubItems.Add(IntToStr(Resources[i].StatusCode))
         end;
   end;

Подобным образом вы можете организовать, например, проход по всему дереву каталогов в аккаунте, запрашивая методом PROPFIND необходимые сведения. Теперь посмотрим как скачивать файлы из аккаунта.

Скачивание файлов с Яндекс.Диска

Вначале посмотрим, что нам говорит документация по поводу метода GET. В принципе тут нет ничего нового по сравнению с обычным GET, который мы уже сто раз использовали в самых разным ситуациях при работе с другими API. Яндекс.Диск также может вернуть нам файл в сжатом виде, если сжатие оправдано (про работу с GZIP я писал в статье «Используем GZip в Synapse.«). Сегодня мы рассмотрим скачивание без использование сжатия.

Дописываем у класса TWebDAVSend следующий метод:

type
  TWebDAVSend = class
  private
    FHTTP: THTTPSend;
    [...]
  public
    [...]
    function Get(const ElementHref:string; var Response:TStream):boolean;
  end;
 
function TWebDAVSend.Get(const ElementHref: string; var Response:TStream): boolean;
var URL: string;
begin
  if not Assigned(Response) then Exit;
  URL:=GetRequestURL(ElementHref,false);
  with FHTTP do
  begin
    Headers.Clear;
    Document.Clear;
    Headers.Add('Authorization: Basic ' + FToken);
    Headers.Add('Accept: */*');
    if HTTPMethod('GET', URL) then
      begin
        Result:=ResultCode=200;
        if not Result then
          raise Exception.Create(IntToStr(ResultCode)+' '+ResultString)
        else
          Document.SaveToStream(Response);
      end
    else
      raise Exception.Create(rsPropfindError+' '+ResultString);
  end;
end;

Метод работает следующим образом: в качестве входных параметров Get принимает путь к ресурсу и поток, в который необходимо поместить скачанные данные. Здесь следует отметить, что ElementHref — это строка, которую мы только что получили из XML, когда парсили список ресурсов (свойство Href). Вначале собирается URL по которому находится файл, затем добавляются заголовки авторизации и выполнятся обычный Get. Если запрос выполнен успешно, то все данные сохраняются в поток Response. Вот и вся работа по скачиванию файлов с Яндекс.Диска :) Осталось проверить эту работу на практике.

Для проверки работы функции скачивания файла с Яндекс.Диска я написал следующий обработчик двойного клика в ListView:

procedure TForm5.ListView1DblClick(Sender: TObject);
var Res:TWDResource;
    Stream:TStream;
begin
  if ListView1.ItemIndex>-1 then
    Res:=Resources[ListView1.ItemIndex];//получили ресурс из списка
  Stream:=TMemoryStream.Create;
  try
    if WebDAV.Get(Res.Href,Stream) then //запрос Get прошел успешно
      TMemoryStream(Stream).SaveToFile(ExtractFilePath(Application.ExeName)+Res.DisplayName);
  finally
    Stream.Free;
  end;
end;

Вид работающего приложения представлен на рисунке ниже:

Осталось только добавить, что если Вы попробуете скачать не файл, а коллекцию, то сервер вполне справедливо ругнется вот такой ошибкой:

Так что даже не пробуйте качать коллекции — только файлы. Вот и всё, что касается темы сегодняшней статьи.

Скачать исходник: Исходники —> API онлайн-сервисов —> Яндекс API

Книжная полка

Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
купить книгу delphi на ЛитРес
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
купить книгу delphi на ЛитРес
0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
53 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Наиль
Наиль
20/07/2012 16:40

Извиняюсь за дублирование сообщения, но без форматирования читать не возможно.
Нет ни чего менее масштабируемого, чем множество вложеных if’ов.
Условия везде одинаковые, поэтому можно разбить «if-Ёлочку» на две части:
1. Поиск в массиве возможных значений.
2. Индекс найденого элемента использовать в качестве аргумента для CASE.

Как-то так:
[code]
ValueIndex := -1;
for I=0 to High(Values) do begin
if not SameText(PropertyNode.NodeName, Values[I]) then Continue;
ValueIndex := I;
break;
end;

case ValueIndex of
0: Resources.Last.FCreationDate:=UTCToSystemTime(ISODateTime2UTC(PropertyNode.Text));
1: Resources.Last.FDisplayName:=Utf8ToAnsi(PropertyNode.Text);
2: Resources.Last.FContentLength:=PropertyNode.NodeValue;
// и т.д.
end;
[/code]
Это решение универсальное (для однотипных условий) и легко масшабируется.

Chrome~
Chrome~
21/07/2012 04:32

Конструкция «if … then … else if …» немножко стремно выглядит.

dimka
dimka
08/10/2012 14:34

У меня на этой строке:
Resources.Last.FHref:=ChildNode.Text
дает ошибку «[DCC Error] Unit1.pas(680): E2018 Record, object or class type required»
Что не так?

Дмитрий Яковлев

Чем можно заменить TMemoryStream для скачки больших файлов?

Дмитрий Яковлев

Пример?

Дмитрий Яковлев

С вами познаю Delphi

Дмитрий Яковлев

Я так понимаю, что с помощью Synapse нельзя реализовать получение файлов больших объемов?
Необходимо переписывать сам Synapse для этого?

Дмитрий Яковлев

Vlad, пробовал по всякому, но не выходит у меня каменный цветок :(
пробовал вместо TMemoryStream создавать TFileStream, но здесь:
WebDAV.Get(Res.Href,Stream)
в Document идет закачка файла в память, причем пытаюсь скачать файл 44 Мб, а в диспетчере задач приложение разрастается до 500 с лишним Мб и вылетает с ошибкой «Out of memory».
Издевался над Document внутри WebDAV.Get, но все равно Document «впитывает» в себя какие-то лишние мегабайты :(
Интернет, сайт и вики синапса рою уже неделю, но не нахожу решения :(
Подскажите как реализовать получение файлов большого объема средствами Synapse, пожалуйста.

Дмитрий Яковлев

В прошлом сообщении ошибся — вместо 44Мб файл размером более 700Мб.
Vlad, установил XE2, установил Synapse, скачал ваш исходник.
При скачивании большого файла приложение yandex_disk.exe разрастается пока весь файл не скачается.

Дмитрий Яковлев
Ответить на  Vlad

Vlad, разобрался с ошибкой «Out of memory» — это была Debug-версия. Не на вашем проекте, на другой простенькой програмке в строке присвоения значения переменной почему-то не работал брикпойнт, стал разбираться и выяснил, что есть Debug и Release версии. Но в Release-версии всё равно при скачивании файлов большого размера приложение увеличивается на размер скачиваемого файла. :( Я так понимаю, что при ответе от сервера (где он отсылает нам файл) мы его принимаем методом Get if WebDAV.Get(Res.Href,Stream) then //запрос Get прошел успешно с помощью Synapse в MemoryStream, наше приложение в это время зависает, а когда Synapse принял полностью, то Synapse нам его… Подробнее »

Антон Исаев
13/03/2013 20:00

Vlad, а Вы не пробовали загружать файлы на Яндекс.Диск по их API?

Антон Исаев
14/03/2013 18:08
Ответить на  Vlad

Вроде бы понял, в чём была проблема — Яндекс.Диск отказывался принимать запросы, если хотя бы раз не загрузить на него файлы вручную. Как только файлы были загружены (и увеличено пространство), сразу всё заработало как надо.

Отдельная благодарность за пример работы с WebDAV! Сам бы доходил до этого о-очень долго. Особенно с интересным поведением Яндекс.Диска при первом знакомстве :)

Анзор
Анзор
21/03/2013 09:48
Ответить на  Антон Исаев

Антон, не могли бы Вы поделиться реализацией метода PUT? Второй день сижу парюсь, не могу никак сделать.

KVGColl
KVGColl
19/03/2013 11:32

Vlad, спасибо за интересную статью, вообщем то благодаря этой статье (ну и документации самого Яндекса) получилось сделать свою программку по работе с Диском. Остался только один вопрос — а как получить статус каждого уже лежащего на Диске файла — т.е. опубликован он или нет. Читал документацию WebDav — там ни одно свойство по PROPFIND не подходит… Не подскажете, куда копать?:)

Андрей
Андрей
24/03/2013 17:09

Vlad, огромное спасибо за статью! Очень сильно помогла в моем проекте.
Столкнулся с проблемой. На моем компьютере все работает как часы. Добавляет, скачивает с Яндекс.Диск. А вот решил попробовать на другом компьютере. Приложение не работает вылетает ошибка «Ошибка при выполнении запроса PROPFIND». Пробовал подключить сетевой диск, все равно вылетает эта ошибка. Установил Яндекс.Диск проблема та же. Не подскажете в чем может быть проблема?
Спасибо.

skuwakin
skuwakin
19/11/2013 18:27

Vlad, доброго времени суток. Опять я за помощью к вам и вашему уникальному ресурсу. Понадобилось считывать файлик с яндекс диска… но… на delphi 7… Вроде все победил, но вот эту строчку

TWDResourceList = class(TList)

точнее вот на это компилятор ругается… если ее убрать то он дальше по тексту ругается, типа надо укзать тип… Насколько я понимаю, эта запись означает «создать список из элементов типа «. А как такое изобразить на D7 не въезжаю… Подскажите плиз…

skuwakin
skuwakin
19/11/2013 18:31

не ну я так не играю… почему ваш сайтик коверкает сообщения-то…
ведт потерялся ВЕСЬ сиысл вопрос из-за выбрасывания [code]"[/code]

skuwakin
skuwakin
19/11/2013 18:33

да что же это творится, третья попытка… TWDResource
последнее слово было в

skuwakin
skuwakin
15/08/2014 17:42

доброго времени суток. возможно ли при помощи indy или т.п. компонетов, скачать файл с я-диска по публичной ссылке?
(http://yadi.sk/d/……) и если да, то подскажите плиз как…
Одно решение в принципе понятно, но уж больно не хочется парсить страницу и пытаться добыть прямую ссыль…

skuwakin
skuwakin
15/08/2014 17:50
Ответить на  Vlad

спасибо за оперативный ответ. Вы мне очень помогли!

skuwakin
skuwakin
17/08/2014 03:08

Доброго времени суток. Еще один вопросик всплыл…. Не получается ни при помощи indy, ни при помощи synapse, загрузить страничку, которую выдает яндекс при попытки скачать файл с яндекс-диска. Не могут они побороть перенаправление (насколько я понял). Не подскажите как все же это осуществить? Оно конечно можно обойтись twebbrowser, но меня забодали запросы безопасности долбанного ie… и отключить это нормально у меня не получилось…

skuwakin
skuwakin
18/08/2014 22:57
Ответить на  Vlad

Спасибо за ответ! Буду много думать. Все проблемы. какие были (кроме редиректа) решил, да и похоже я тут с indy, synapce в принципе не прав… они для такого финта не годятся, они же javascript не исполняют… В итоге, сел за чтение API яндекса…

Akella
21/11/2014 18:32

А как быть, если нужно только опубликовать файл?
Т.е. папку с кучей файлов пользователь сам закидывает в локальную папку ПК. Утилита Диск-Яндекс эту папку синхронизирует.
А моя программа должна только
1. Дать команду опубликовать файл (сделать его доступным для всех)
2. При этом сразу получить ссылку на опубликованный файл?

Т.е. выгружать ненужно…

Akella
21/11/2014 20:01
Ответить на  Vlad

это оно?
https://tech.yandex.ru/disk/doc/dg/reference/publish-docpage/#publish-s

но как отправить такой PROPPATCH-запрос?

Akella
24/11/2014 21:05

оказывается у InDy есть уже готовый модуль IdWebDAV

Akella
24/11/2014 21:35
Ответить на  Vlad

К сожалению, нет ни описания, ни примеров :(

Akella
24/11/2014 21:48

У меня получается так:

procedure TForm2.Button1Click(Sender: TObject);
Var
s, r: TStringStream;
begin
s := TStringStream.Create(» + sLineBreak +
» + sLineBreak +
» + sLineBreak +
‘true’ + sLineBreak +
» + sLineBreak +
» + sLineBreak +
»);

r := TStringStream.Create(»);
try
IdWebDAV1.URL.Password := ‘***@yandex.ru’;
IdWebDAV1.URL.Username := ‘***’;
IdWebDAV1.URL.Port := ’80’;
IdWebDAV1.URL.URI := ‘/tst/readme.txt’;
IdWebDAV1.URL.Host := ‘webdav.yandex.ru’;
IdWebDAV1.URL.Protocol := ‘PROPFIND’;
IdWebDAV1.Put(‘https://webdav.yandex.ru/’, s, r);

Memo1.Lines.Text := r.DataString;
finally
s.Free;
r.Free;
end;
end;

не могу понять, куда вставить этот токен, который я получил от яндекса
в документации https://tech.yandex.ru/disk/doc/dg/reference/publish-docpage/#publish-s
вот он:
Authorization: OAuth 0c4182a7c2cf4521964a72ff57a34a07

Akella
25/11/2014 13:43

добавил
IdWebDAV1.Request.CustomHeaders.AddValue(‘Authorization’, ‘OAuth c953e55d5ec14595ag116f33143e73b3’);

выдаёт: HTTP/1.1 401 Unauthorized.

Akella
25/11/2014 15:36

Поменял на
IdWebDAV1.Request.Username := ‘***@yandex.ru’;
IdWebDAV1.Request.Password := ‘*******’;
IdWebDAV1.Request.Method := ‘PROPFIND’;

теперь выдаёт: HTTP/1.1 405 Method Not Allowed.

Akella
25/11/2014 16:09

В статье ни слова о том, что это за Token?

На сайте Яндекса написано, что некий OAuth token ID нужно получать
https://tech.yandex.ru/disk/webdav/
https://tech.yandex.ru/oauth/

Akella
25/11/2014 20:30

Просто у меня не Basic утентификация.

>>OAuth-токен вечный
Ну… я думаю, что за 1-2 дня не протухнет.

>>Вы точно разбираетесь в том, что пробуете сделать?
Если бы разбирался, то вопросов бы не было. Пытаюсь разобраться.

Akella
25/11/2014 20:41

За ссылки спасибо!

Akella
25/11/2014 20:52

Ну я так понял, что если у меня есть OAuth токен, то логин/пароль можно не передавать.
Теперь дошло.

IdWebDAV1.Request.Method := 'PROPPATCH';
IdWebDAV1.Request.Host := 'webdav.yandex.ru';
IdWebDAV1.URL.URI := '/tst/readme.txt';
IdWebDAV1.URL.Host := 'webdav.yandex.ru';
IdWebDAV1.Request.Source := s;
IdWebDAV1.Request.ContentType := 'application/x-www-form-urlencoded';

IdWebDAV1.Request.CustomHeaders.Add('Authorization: OAuth c412e33d6ec24895aa116f33143e73b3');
IdWebDAV1.Post('https://oauth.yandex.ru/verification_code', s, r);

Андрей
Андрей
27/08/2015 16:19

На Андроид не будет компилиться… Чем заменить ингредиенты-участники?

Евгений Картаев

Здравствуйте. Спасибо автору за статьи. С интересом изучаю.
Подскажите по 2м вопросам:
1. Как понимать выражение типа «Result:=ResultCode=200». Я так понимаю что это присвоение с условием? Т.е. если ResultCode будет равен 200, то к Result присвоится значение 200?
2. Где нужно указать куда сохранить файл при скачивании с Яндекс.Диск? По умолчанию файл скачивается в папку с программой
Заранее спасибо