Unity3d: Запись файла на Yandex диск на C#

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

К моему удивлению, на столь популярный сервис, как Яндекс диск, не нашлось примеров записи файла на диск на языке программирования C#. На PHP же ситуация обратная, примеров вдоволь, например: https://snipp.ru/php/disk-yandex

Я, как человек, который практически не изучал веб, потратил сутки, чтобы разобраться, что к чему. Надеюсь, эта статья поможет кому-нибудь сэкономить время.

Итак, приступим. Первое, что вам необходимо сделать, это зарегистрировать своё приложение: https://oauth.yandex.ru/ На этом этапе ничего сложного нет, просто важно дать доступ REST API к нашему диску.

После того, как вы зарегистрировались, вы получите код ClientID OAuth. Он то нас и интересует.

Я использовал только простейший способ получения отладочного токена:
Переходим по ссылке, не забывая заменить в ней идентификатор приложения на полученный OAuth.
https://oauth.yandex.ru/authorize?response_type=token&client_id=<идентификатор приложения (OAuth)>

Вам выдастся код - токен.

Теперь, чтобы записать файл на диск, необходимо выполнить 2 http запроса. GET для получения url, на который мы будем заливать наш файл и PUT для загрузки этого файла.
(Об этом можно прочесть в официальной документации https://yandex.ru/dev/disk/api/reference/upload.html#response-upload)

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

using UnityEngine;
using System.Net;
using System.Net.Http;
public class BackUpOnYandex : MonoBehaviour
{
    [Header("Отладочный токен")]
    public string token = "";
    [Header("Путь к файлу на компьютере")]
    public string path = "";
    [Header("Путь к файлу на диске")]
    public string path_disk = "";

    [Button(nameof(SaveAsync))]
    public bool buttonField;
    public async System.Threading.Tasks.Task SaveAsync()
    {
        await testAsync();
        await testAsync2();
    }

    public async System.Threading.Tasks.Task testAsync()
    {//Информация о диске
        HttpClient client = new HttpClient();

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://cloud-api.yandex.net/v1/disk");

        request.Headers.Add("Accept", "application/json");
        request.Headers.Add("Authorization", $"OAuth {token}");

        HttpResponseMessage response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
        string responseBody = await response.Content.ReadAsStringAsync();
        Debug.Log("Информация о диске");
        Debug.Log(responseBody);

    }
    public async System.Threading.Tasks.Task testAsync2()
    {//ссылка для загрузки файла
        HttpClient client = new HttpClient();

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://cloud-api.yandex.net/v1/disk/resources/upload?path=" + path_disk + "&overwrite=true");

        request.Headers.Add("Accept", "application/json");
        request.Headers.Add("Authorization", $"OAuth {token}");

        HttpResponseMessage response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
        string responseBody = await response.Content.ReadAsStringAsync();
        Debug.Log("Пришедший JSON:");
        Debug.Log(responseBody);
        int indexOfSubstring = responseBody.IndexOf("https");
        responseBody = responseBody.Substring(indexOfSubstring);
        int indexOfSubstring2 = responseBody.IndexOf("\"");
        responseBody = responseBody.Substring(0, indexOfSubstring2);
        Debug.Log("Ссылка для загрузки файла:" + responseBody);
        HTTP_PUT(responseBody, path);

    }

    // HTTP_PUT Function Метод загрузки файла на url
    public void HTTP_PUT(string Url, string filePath)
    {
        Debug.Log("Загружаем файл POST запросом");
        using (WebClient client = new WebClient())
        {
            client.UploadFile(Url, filePath);
        }
        Debug.Log("Загружено");
    }
}

В скрипте для удобства используется отображение кнопки в редакторе, найденное где-то на просторах интернета:

using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif

#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(ButtonAttribute))]
public class ButtonDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        string methodName = (attribute as ButtonAttribute).MethodName;
        Object target = property.serializedObject.targetObject;
        System.Type type = target.GetType();
        System.Reflection.MethodInfo method = type.GetMethod(methodName);
        if (method == null)
        {
            GUI.Label(position, "Method could not be found. Is it public?");
            return;
        }
        if (method.GetParameters().Length > 0)
        {
            GUI.Label(position, "Method cannot have parameters.");
            return;
        }
        if (GUI.Button(position, method.Name))
        {
            method.Invoke(target, null);
        }
    }
}
#endif

public class ButtonAttribute : PropertyAttribute
{
    public string MethodName { get; }
    public ButtonAttribute(string methodName)
    {
        MethodName = methodName;
    }
}

При написании этого кода мне очень помогло 2 ссылки:

  • Яндекс полигон. С него бралось cURL https://yandex.ru/dev/disk/poligon/

  • Конвертер cURL в http request С# (и не только) https://curlconverter.com/csharp/

Источник: https://habr.com/ru/post/710994/


Интересные статьи

Интересные статьи

Разработчики предъявляют высокие требования к базам данных: максимальная надежность (ничего из того, что было записано не должно быть утеряно ни при каких обстоятельствах), и, одновременно, максимальн...
Статья направлена на решение проблемы "зависания" выгрузки результатов опросов при использовании модуля Vote 1С-Битрикс в случае, если в опросе много вопросов или ответов. Так-же в статье реализована ...
Вчера на Хабре публиковалась новость о том, что любой желающий снова может купить себе видеокарту, причем в любом количестве и по гораздо, гораздо более низким ценам, чем всего несколько месяцев наз...
В один из вечеров у меня появились наукообразные вопросы. Можно ли «растворить» какой-либо видеофайл, разместив его в теле другого видеофайла так, чтобы при этом первый видеофайл можно было относитель...
С момента покупки моих первых минидисковых устройств прошло три года, и я должен признать, что хобби окончательно вышло из-под контроля. Оно находится в стадии «эксплуатация»: все, что я хотел узнать ...