我想在我的SFTP下载中包含一个进度条,以便用户理解这只是一个大文件,并且进度没有冻结/锁定。我偶然发现了this的nuget程序包,它看起来确实可以满足我的需要,但是由于我使用的是SFTP,因此要获取正在下载的文件的总文件大小,并希望更新进度条尽可能真实地取决于已传输了多少文件。
如果我正确理解此代码-我将仅提供“总滴答”计数,该计数与文件大小完全无关,因此进度指示将不准确。如何根据文件大小显示实际进度?
const int totalTicks = 10;
var options = new ProgressBarOptions
{
ProgressCharacter = '─',
ProgressBarOnBottom = true
};
using (var pbar = new ProgressBar(totalTicks, "Initial message", options))
{
pbar.Tick(); //will advance pbar to 1 out of 10.
//we can also advance and update the progressbar text
pbar.Tick("Step 2 of 10");
}
修改
经过一些谷歌搜索和大量的反复试验后,我想到了下面的语法,其功能几乎与我想要的一样。我的问题是进度条将仅显示FIRST文件的进度,因此它将“紧密地”显示第一个文件的文件传输进度,当达到100%时,它只会坐在那里而不会显示进度后续文件。
我需要在下面的代码中进行哪些更改,以显示从目录下载的所有文件的文件进度?
注意***以下代码中未声明的任何变量在我的代码中都声明为私有const变量
static void Main(string[] args)
{
var options = new ProgressBarOptions
{
ProgressCharacter = '.',
ProgressBarOnBottom = true
};
using (var pbar = new ProgressBar(totalTicks, "Starting To Download Files....", options))
DownloadFile(spvalues.an, spvalues.lt, b, d, username, password, pbar, totalTicks, 500);
}
private static void DownloadFile(string username, string password, ProgressBar pbar, int totalTicks, int sleep)
{
for (int i = 0; i < totalTicks; i++)
{
Task.Delay(sleep).Wait();
pbar.Tick();
}
using (var sftp = new SftpClient(Host, username, password))
{
sftp.Connect();
string fullpath = RemoteDir + d + "/" + customer;
var files = sftp.ListDirectory(fullpath);
foreach (var file in files)
{
SftpFileAttributes att = sftp.GetAttributes(fullpath + "/" + file.Name);
var fileSize = att.Size;
var ms = new MemoryStream();
IAsyncResult asyncr = sftp.BeginDownloadFile(fullpath + "/" + file.Name, ms);
SftpDownloadAsyncResult sftpAsyncr = (SftpDownloadAsyncResult)asyncr;
int lastpct = 0;
while (!sftpAsyncr.IsCompleted)
{
int pct = (int)((long)sftpAsyncr.DownloadedBytes / fileSize) * 100;
if (pct > lastpct)
for (int i = 1; i < pct - lastpct; i++)
pbar.Tick();
}
sftp.EndDownloadFile(asyncr);
string localFilePath = "C:\\" + file.Name;
var fs = new FileStream(localFilePath, FileMode.Create, FileAccess.Write);
ms.WriteTo(fs);
fs.Close();
ms.Close();
}
}
}
答案 0 :(得分:0)
由于我认为没有其他人可以帮助您:看着那个包装看起来很漂亮,但是只是为了证明它仍然可以工作,这不是过分的杀伤力吗?现在,我可能还不是100%,但是您要做的是使用线程。这意味着您可以同时运行两个进程。一个线程将每秒钟左右更新一次控制台,而另一个线程将下载SFTP文件。一旦STFP文件下载完成,更新线程将被杀死。
如果您想显示状态,那么在不知道代码确切细节的情况下,我不能真正建议您,但是您可以检查Filestream的位置以获取总数的百分比。
状态线程将使用类似于以下内容的方式每秒更新一次:
public void foo()
{
Task.Delay(1000).ContinueWith(t=> bar());
}
public void bar()
{
// do stuff like check that the FileStream position has moved and change the console text
}
除此之外,还有很多事情要做,我不会为您编写所有代码,但希望可以为您指明一个方向(可能不是最好的方向)。