c# - 如何在 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;
}
解决方案
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
此代码仅显示和应该使用的实现,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
方法的末尾来避免这种情况,但要了解线程现在保留在这里直到完成。因此,如果它是 UI 线程,您会遇到复杂情况,并且可能会丢失对进度条的更新。这个想法是你希望这个调用是异步的,但是为了知道下面的行是.Result;
添加的。
INode myFile = myMegaClient.UploadFileAsync(filePathOnComputer, myFolderOnMega, progress, uploadCancellationTokenSource.Token).Result;
如果您愿意,还可以使用实际调用的代码更新您的问题,uploadToMega
我将向您展示我们如何更新该部分。最后,这种变化将受到赞赏。
为了更好地了解这里发生了什么,我建议您查看Task
类型,了解它的工作原理,并查看async await
允许您以Task
更轻松的内联方式使用的关键字。
请随时将整个项目发送给 michael_puckett_ii@hotmail.com,我会对其进行更新,清除所有编译错误,并为您留下一些评论,以帮助您在需要时了解更改。
推荐阅读
- javascript - 如何修复'脚本应该为每个类'列表'创建下拉选项'
- postgresql - 无法使用 postgraphile 连接数据库
- oauth - Angular6 oauth 令牌验证
- libwebsockets - 使用 libwebsockets 写入部分数据
- python - 为什么在 Keras 的多类分类中 binary_crossentropy 比 categorical_crossentropy 表现更好?
- angular - 在角度模板中为嵌套属性放置多个问号是否正确?
- javascript - 正则表达式提取字符串单词
- string - if-Condition 中的批处理字符串 abschneiden
- javascript - 使用编码 UCS-2 LE BOM 或 Unicode 创建 .txt 文件
- node.js - 如何在 AWS Lambda 中分块执行我的 nodejs 代码