如何在Mega API中制作UploadFileAsync

时间:2018-05-04 12:00:16

标签: c# api file-upload

我是C#的新手,这是我第一次使用此API

我正在尝试通过C#App将文件上传到我的大型帐户

我成功上传但没有任何进度条

并且API具有此方法" UploadFileAsync "但我无法理解这个方法中的每个参数

这是来自VS中的对象浏览器

  

IMegaApiClient.UploadFileAsync(string,CG.Web.MegaApiClient.INode,   System.IProgress,System.Threading.CancellationToken?)

     

System.Threading.Tasks.Task   UploadFileAsync(string filename,CG.Web.MegaApiClient.INode parent,   System.IProgress进度,   [System.Threading.CancellationToken? cancellationToken = null])       CG.Web.MegaApiClient.IMegaApiClient成员

我知道文件名和INode父级 但 我该怎么写" System.IProgress进展" 和cancellationToken

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 :(得分:3)

System.IProgress是一个使用的接口,因此我们可以编写自定义进度类型并与内置的进行交换。它有一个方法Report(T),其中T是匿名类型。< / p>

这意味着您可以编写自己的进度类,但是已经有一个已经用.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没有&{} #39; t总是必须是一个正在运行的线程。无论如何,重点是我们使用CancellationToken来表示取消Task。由于此UploadFileAsync是不同API的一部分,因此我们不必担心处理CancelationToken,但我们可以提供一个尝试,以便我们可以尝试取消上传。请注意,取决于API并取消Task可能会引发错误(通常为OperationCanceledException)或类似错误。无论如何,如果你提供了令牌,那么还要测试取消它以查看它是如何发挥作用的。

在此代码示例中,我将向您展示如何提供CancellationToken请记住,您可以从另一个可能类似(停止上传)的按钮调用此令牌的取消。

首先,我们将制作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。此代码仅显示IDisposableCancellationTokenSource的实现,应该使用,但它最适合您的应用程序。

如果您正在使用自己的班级......(从技术上讲,我们应该将此标记为密封或提供​​并覆盖Dispose(bool),但仅仅是为了解释它是这样的。< / p>

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方法的末尾,但要了解该线程现在在此处保留完成。因此,如果它是UI线程,您将会遇到并发症,并可能失去对进度条的更新。这个想法是你希望这个调用是异步的,但为了知道这里添加了.Result;的下面一行。

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

如果您愿意,还可以使用实际调用uploadToMega的代码更新您的问题,并且我将向您展示我们如何更新该部分。最后,我们将不胜感激。

为了更好地了解此处发生了什么,我建议您查看Task类型,了解其工作原理,并查看允许您使用的async await关键字Task以更简单的内联方式。

随时将整个项目发送给我michael_puckett_ii@hotmail.com,我会更新它,清除所有编译错误,并留下一些评论,以帮助您了解更改,如果您需要。< / p>