Как я могу сделать UploadFileAsync в Mega API - PullRequest
0 голосов
/ 04 мая 2018

Я новичок в C #, и я впервые использую этот API

Я пытаюсь загрузить файл на мой мега-аккаунт с помощью приложения C #

и мне удалось загрузить, но без индикатора выполнения

и API имеет этот метод " UploadFileAsync ", но я не могу понять каждый параметр в этом методе

это из Обозревателя объектов в VS

IMegaApiClient.UploadFileAsync (строка, CG.Web.MegaApiClient.INode, System.IProgress, System.Threading.CancellationToken?)

System.Threading.Tasks.Task UploadFileAsync (строка имени файла, CG.Web.MegaApiClient.INode parent, System.IProgress прогресс, [System.Threading.CancellationToken? cancellationToken = null]) Член CG.Web.MegaApiClient.IMegaApiClient

я знаю имя файла и родителя INode но что я должен написать в "System.IProgress Прогресс" и отмена взята

public uploadFileData uploadToMega(string megaFolderName, string megaFolderID, string filePathOnComputer, string newFileNameOnMega)
        {
            //Implemnt Struct
            uploadFileData myMegaFileData = new uploadFileData();

            //Start Mega Cient
            var myMegaClient = new MegaApiClient();

            //Login To Mega
            myMegaClient.Login(Userrrr, Passss);

            //Get All (File & Folders) in Mega Account
            IEnumerable<INode> nodes = myMegaClient.GetNodes();

            //Creat List Of All Folders In Mega Account
            List<INode> megaFolders = nodes.Where(n => n.Type == NodeType.Directory).ToList();

            //Choose Exist Folder In Mega Account By Name & Id
            INode myFolderOnMega = megaFolders.Where(folder => folder.Name == megaFolderName && folder.Id == megaFolderID).FirstOrDefault();


            //Upload The File
            //Normal Upload
            //INode myFile = myMegaClient.UploadFile(filePathOnComputer, myFolderOnMega);

            // Upload With progress bar
            INode myFile =  myMegaClient.UploadFileAsync(filePathOnComputer, myFolderOnMega, progressBar1, default());


            //Rename The File In Mega Server
            if (string.IsNullOrEmpty(newFileNameOnMega))
            {

            }
            else
            {
                myMegaClient.Rename(myFile, newFileNameOnMega);
            }

            //Get Download Link
            Uri downloadLink = myMegaClient.GetDownloadLink(myFile);

            myMegaFileData.megaFileId = myFile.Id;
            Clipboard.SetText(myMegaFileData.megaFileId);
            myMegaFileData.megaFileType = myFile.Type.ToString();
            myMegaFileData.megaFileName = myFile.Name;
            myMegaFileData.megaFileOwner = myFile.Owner;
            myMegaFileData.megaFileParentId = myFile.ParentId;
            myMegaFileData.megaFileCreationDate = myFile.CreationDate.ToString();
            myMegaFileData.megaFileModificationDate = myFile.ModificationDate.ToString();
            myMegaFileData.megaFileSize = myFile.Size.ToString();
            myMegaFileData.megaFileDownloadLink = downloadLink.ToString();



            myMegaClient.Logout();



            return myMegaFileData;
        }

1 Ответ

0 голосов
/ 04 мая 2018

System.IProgress - это интерфейс, используемый для того, чтобы мы могли писать собственные типы прогресса и обмениваться ими со встроенными. Он имеет один метод Report(T), где T - анонимный тип.

Это означает, что вы можете написать свой собственный класс прогресса, но в .NET уже есть класс с таким интерфейсом, и, так как он соответствует требованиям, давайте его использовать. Он находится в том же пространстве имен, что и IProgress<T>, и является Progress, и поставляется с удобным встроенным событием ProgressChanged, которое мы можем прослушивать. Так что в этом примере кода первого шага я только представляю прогресс. Обратите внимание, что я заменил ProgressBar на переменную progress в коде.

var progress = new Progress<double>();
progress.ProgressChanged += (s, progressValue) =>
{
    //Update the UI (or whatever) with the progressValue 
    progressBar1.Value = Convert.ToInt32(progressValue);
};

INode myFile = myMegaClient.UploadFileAsync(filePathOnComputer, myFolderOnMega, progress, default());

Теперь я не буду преподавать вам урок по Task, но знаю, что о Task можно думать по-разному, как о потоках, но знайте, что Task не всегда должен быть запущенным нить. В любом случае, дело в том, что мы используем CancellationToken, чтобы сигнализировать об отмене Task. Так как этот UploadFileAsync является частью другого API, нам не нужно беспокоиться об обработке CancelationToken, но мы можем предоставить один из них, чтобы попытаться отменить загрузку, если захотим. Просто обратите внимание, что в зависимости от API и отмены Task потенциально может выдать ошибку (обычно OperationCanceledException) или подобное. В любом случае, если вы предоставили токен, проверьте также его отмену, чтобы увидеть, как все это закончится.

В этом примере кода я покажу вам, как вы предоставляете CancellationToken. Помните, что вы можете вызвать отмену на этом токене с другой кнопки, которая может сказать что-то вроде (Stop Upload).

Итак, во-первых, мы сделаем CancellationTokenSource и сделаем его на уровне class, чтобы мы могли использовать его в любом месте нашего класса.

private CancellationTokenSource uploadCancellationTokenSource = new CancellationTokenSource();

Затем, перед нашим UploadFileAsync вызовом, мы должны убедиться, что он никогда не был отменен, и, если он есть, мы должны возобновить его.

if (uploadCancellationTokenSource.IsCancellationRequested)
{
    uploadCancellationTokenSource.Dispose();
    uploadCancellationTokenSource = new CancellationTokenSource();
}

INode myFile = myMegaClient.UploadFileAsync(filePathOnComputer, myFolderOnMega, progress, uploadCancellationTokenSource.Token);

И ... мы можем добавить событие нажатия кнопки или что-то, чтобы отменить токен, если захотим.

private void CancelUploadButtonClick(object sender, EventArgs e)
{
    if (!uploadCancellationTokenSource.IsCancellationRequested)
        uploadCancellationTokenSource.Cancel();
}

Надеюсь, вы немного больше поймете, что происходит и как это реализовать. Вот лишь пример ложного кода всего изменения на вашем примере:

private CancellationTokenSource uploadCancellationTokenSource = new CancellationTokenSource();

public async Task<uploadFileData> uploadToMegaAsync(string megaFolderName, string megaFolderID, string filePathOnComputer, string newFileNameOnMega)
{
    //Implemnt Struct
    uploadFileData myMegaFileData = new uploadFileData();

    //Start Mega Cient
    var myMegaClient = new MegaApiClient();

    //Login To Mega
    myMegaClient.Login(Userrrr, Passss);

    //Get All (File & Folders) in Mega Account
    IEnumerable<INode> nodes = myMegaClient.GetNodes();

    //Creat List Of All Folders In Mega Account
    List<INode> megaFolders = nodes.Where(n => n.Type == NodeType.Directory).ToList();

    //Choose Exist Folder In Mega Account By Name & Id
    INode myFolderOnMega = megaFolders.Where(folder => folder.Name == megaFolderName && folder.Id == megaFolderID).FirstOrDefault();

    //Upload The File
    //Normal Upload
    //INode myFile = myMegaClient.UploadFile(filePathOnComputer, myFolderOnMega);

    //NEWLY ADDED
    var progress = new Progress<double>();
    progress.ProgressChanged += (s, progressValue) =>
    {
        //Update the UI (or whatever) with the progressValue 
        progressBar1.Value = Convert.ToInt32(progressValue);
    };

    //NEWLY ADDED
    if (uploadCancellationTokenSource.IsCancellationRequested)
    {
        uploadCancellationTokenSource.Dispose();
        uploadCancellationTokenSource = new CancellationTokenSource();
    }

    // Upload With progress bar
    INode myFile = await myMegaClient.UploadFileAsync(filePathOnComputer, myFolderOnMega, progress, uploadCancellationTokenSource.Token);

    //Rename The File In Mega Server
    if (string.IsNullOrEmpty(newFileNameOnMega))
    {

    }
    else
    {
        myMegaClient.Rename(myFile, newFileNameOnMega);
    }

    //Get Download Link
    Uri downloadLink = myMegaClient.GetDownloadLink(myFile);

    myMegaFileData.megaFileId = myFile.Id;
    Clipboard.SetText(myMegaFileData.megaFileId);
    myMegaFileData.megaFileType = myFile.Type.ToString();
    myMegaFileData.megaFileName = myFile.Name;
    myMegaFileData.megaFileOwner = myFile.Owner;
    myMegaFileData.megaFileParentId = myFile.ParentId;
    myMegaFileData.megaFileCreationDate = myFile.CreationDate.ToString();
    myMegaFileData.megaFileModificationDate = myFile.ModificationDate.ToString();
    myMegaFileData.megaFileSize = myFile.Size.ToString();
    myMegaFileData.megaFileDownloadLink = downloadLink.ToString();

    myMegaClient.Logout();

    return myMegaFileData;
}

private void CancelUploadButtonClick(object sender, EventArgs e)
{
    if (!uploadCancellationTokenSource.IsCancellationRequested)
        uploadCancellationTokenSource.Cancel();
}

Я собираюсь закончить еще одним советом. Поскольку у нас есть одноразовый тип класса (CancelletionTokenSource), мы должны правильно реализовать IDisposable в вашем классе. Это код, показывающий ТОЛЬКО реализацию IDisposable и CancellationTokenSource, и его следует использовать, однако он лучше всего подходит для вашего приложения.

Если вы используете свой собственный класс ... (технически мы должны пометить это как запечатанный или предоставить и перезаписать Dispose(bool), но просто для объяснения это так.

public class Example : IDisposable
{
    private CancellationTokenSource uploadCancellationTokenSource = new CancellationTokenSource();
    public void Dispose()
    {
        uploadCancellationTokenSource.Dispose();
        GC.SuppressFinalize(this);
    }
    ~Example() => Dispose();
}

Если вы находитесь в WinForm или другом унаследованном классе, в котором уже реализовано IDisposable.

public class Example2 : Example
{
    private CancellationTokenSource uploadCancellationTokenSource = new CancellationTokenSource();
    public new void Dispose()
    {
        uploadCancellationTokenSource.Dispose();
        base.Dispose();
    }
}

Хорошо, наконец, я обновил метод uploadToMega в приведенном выше коде для чтения в качестве задачи. Это означает, что вызывающий метод, который использует uploadToMega, теперь должен будет также использовать async в сигнатуре метода и await в вызове. Примечание: вы можете избежать этого, оставив вещи такими же, какими они были до добавления async await и просто добавив .Result в конец метода UploadFileAsync, но понимая, что поток теперь удерживается здесь до тех пор, пока не завершится. Так что, если это поток пользовательского интерфейса, вы получите осложнения и, возможно, потеряете обновление на индикатор выполнения. Идея состоит в том, что вы хотите, чтобы этот вызов был асинхронным, но для понимания, вот строка ниже с добавленным .Result;.

INode myFile = myMegaClient.UploadFileAsync(filePathOnComputer, myFolderOnMega, progress, uploadCancellationTokenSource.Token).Result;

Если вы хотите, также обновите ваш вопрос кодом, который на самом деле вызывает uploadToMega, и я покажу вам, как мы можем обновить эту часть. В конце концов это изменение будет оценено.

Чтобы лучше понять, что здесь происходит, я советую вам взглянуть на тип Task, понять, как он работает, а также посмотреть на ключевые слова async await, которые позволяют работать с Task в более удобной форме. .

Не стесняйтесь, присылайте мне весь проект на michael_puckett_ii@hotmail.com, и я обновлю его, уберу все ошибки компиляции и оставлю некоторые комментарии, чтобы помочь вам понять изменения, если вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...