首页 > 解决方案 > 如何在 Mega API 中制作 UploadFileAsync

问题描述

我正在尝试通过 C# App 将文件上传到我的超级帐户,并且我成功上传但没有任何进度条,并且 API 具有此方法“ UploadFileAsync ”,但我无法理解此方法中的每个参数。

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

IMegaApiClient.UploadFileAsync(字符串,CG.Web.MegaApiClient.INode,System.IProgress,System.Threading.CancellationToken?)

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

我知道文件名和 INode 父级,但我应该写System.IProgress<double> progress什么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;
        }

标签: c#apifile-upload

解决方案


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

这意味着您可以编写自己的进度类,但是已经用 .NET 编写了一个具有该接口的类,既然它符合条件,我们就使用它。它与IProgress<T>和 is 位于相同的命名空间中,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可以用很多方式来思考,比如线程,但知道 aTask并不总是必须是一个正在运行的线程。无论如何,关键是我们使用 aCancellationToken来表示取消 a 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)它,但只是为了解释起见,它就像这样。

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并简单地添加.ResultUploadFileAsync方法的末尾来避免这种情况,但要了解线程现在保留在这里直到完成。因此,如果它是 UI 线程,您会遇到复杂情况,并且可能会丢失对进度条的更新。这个想法是你希望这个调用是异步的,但是为了知道下面的行是.Result;添加的。

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

如果您愿意,还可以使用实际调用的代码更新您的问题,uploadToMega我将向您展示我们如何更新该部分。最后,这种变化将受到赞赏。

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

请随时将整个项目发送给 michael_puckett_ii@hotmail.com,我会对其进行更新,清除所有编译错误,并为您留下一些评论,以帮助您在需要时了解更改。


推荐阅读