为什么当向进度栏报告每个文件下载的过程时,它永远不会达到 100%
本文关键字:永远 100% 过程 报告 文件下载 为什么 | 更新日期: 2023-09-27 18:33:49
这是从ftp服务器下载文件的方法:
public void DownloadFtpContent(object sender ,string file, string filesdirectories,string fn)
{
try
{
BackgroundWorker bw = sender as BackgroundWorker;
string filenameonly = Path.GetFileName(file);
string ftpdirectories = Path.Combine(ftpcontentdir, filesdirectories);
string fileurl = "ftp://" + file;
FtpWebRequest reqFTP;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(fileurl);
reqFTP.Credentials = new NetworkCredential(UserName, Password);
reqFTP.UseBinary = true;
reqFTP.UsePassive = true;
reqFTP.KeepAlive = true;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.Proxy = null;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream responseStream = response.GetResponseStream();
if (!Directory.Exists(ftpdirectories))
{
Directory.CreateDirectory(ftpdirectories);
}
FileStream writeStream = new FileStream(ftpdirectories + "''" + filenameonly, FileMode.Create);
string fnn = ftpdirectories + "''" + filenameonly;
int Length = 2048;
Byte[] buffer = new Byte[Length];
int bytesRead = responseStream.Read(buffer, 0, Length);
string SummaryText = String.Format("File Name {0} / {1}", "", filenameonly);
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = responseStream.Read(buffer, 0, Length);
var progress = bytesRead * 100.0 / writeStream.Length;
bw.ReportProgress((int)progress,SummaryText);
}
writeStream.Close();
response.Close();
}
catch (WebException wEx)
{
}
}
}
该方法每次从 form1 后台工作线程执行工作事件获取文件。然后我向后台工作人员报告每个文件下载进度以及文件名:
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = responseStream.Read(buffer, 0, Length);
var progress = bytesRead * 100.0 / writeStream.Length;
bw.ReportProgress((int)progress,SummaryText);
}
这是后台工作者 prgoresschanged 事件:
private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.toolStripStatusLabel2.Text = e.UserState.ToString();
this.toolStripProgressBar2.Value = Math.Min(this.toolStripProgressBar2.Maximum, e.ProgressPercentage);
}
报告文件名很好。但是每个文件下载的进度都不好。
每次下载文件时,我都会看到进度栏中的绿色有时移动到 10%,然后回到 0 有时移动到 35%,然后回到 0 有时到 40%,然后一直回到 0 它一直在移动一些然后回到 0 它永远不会到达 100%
问题出在进度更改事件和我获取报告的方式上:
this.toolStripProgressBar2.Value = Math.Min(this.toolStripProgressBar2.Maximum, e.ProgressPercentage);
或者也许在下载方法中,我计算并向进度栏报告的方式:
var progress = bytesRead * 100.0 / writeStream.Length;
bw.ReportProgress((int)progress,SummaryText);
摘要文本报告工作正常,我认为问题出在进度变量上。
你的数学问题就在这里:
writeStream.Write(buffer, 0, bytesRead);
bytesRead = responseStream.Read(buffer, 0, Length);
var progress = bytesRead * 100.0 / writeStream.Length;
bw.ReportProgress((int)progress,SummaryText);
responseStream.Read
的返回值是您在该一次读取中读取的字节数。这不是自您开始读取文件以来读取的总字节数。
此外,将读取的字节数除以写入的总数(即 writeStream.Length
(没有告诉你任何有用的东西。
如果要更新进度条,则必须知道文件中的总字节数,以及到目前为止已读取的总字节数。因此,如果文件长度为 1,000,000 字节,而您总共读取了 450,000 字节,则进度将为 45%(即 450000/1000000(。
在您的代码中,您必须从FTP服务器获取文件大小。这是您要下载的总字节数。然后,您需要跟踪到目前为止已读取的字节数。基本思想是:
int totalBytesToBeRead = ??; // somehow get length. responseStream.Length doesn't work.
int totalBytesRead = 0;
int bytesRead = -1;
while (bytesRead != 0)
{
bytesRead = responseStream.Read(...);
// now add to the total
totalBytesRead += bytesRead;
var progress = totalBytesRead * 100.0 / totalBytesToRead;
}
更新
问题似乎是FtpWebRequest
不提供ContentLength
,所以你需要一些其他方法来获得长度。唯一想到的是通过使用GetFileSize
方法进行单独的FtpWebRequest
来预先请求长度。有关示例,请参阅在 C# 中获取 FTP 上的文件大小。