我们如何使用FtpWebRequest显示上传进度条

我使用FtpWebRequest将文件上传到ftp。 我需要显示已完成的状态。

到目前为止我的代码是:

 public void Upload(string filename, string url) { FileInfo fileInf = new FileInfo(filename); string uri = "ftp://" + url + "/" + fileInf.Name; FtpWebRequest reqFTP; //string uri = "ftp://" + Host + "/public_html/testing/blogtest/" + fileInf.Name; // Create FtpWebRequest object from the Uri provided reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); // Provide the WebPermission Credintials reqFTP.Credentials = new NetworkCredential(Username, Password); // By default KeepAlive is true, where the control connection is not closed // after a command is executed. reqFTP.KeepAlive = false; //reqFTP.UsePassive = true; // Specify the command to be executed. reqFTP.Method = WebRequestMethods.Ftp.UploadFile; // Specify the data transfer type. reqFTP.UseBinary = true; // Notify the server about the size of the uploaded file reqFTP.ContentLength = fileInf.Length; // The buffer size is set to 2kb int buffLength = 2048; byte[] buff = new byte[buffLength]; int contentLen; // Opens a file stream (System.IO.FileStream) to read the file to be uploaded FileStream fs = fileInf.OpenRead(); // Stream to which the file to be upload is written Stream strm = reqFTP.GetRequestStream(); // Read from the file stream 2kb at a time contentLen = fs.Read(buff, 0, buffLength); // Till Stream content ends while (contentLen != 0) { // Write Content from the file stream to the FTP Upload Stream strm.Write(buff, 0, contentLen); contentLen = fs.Read(buff, 0, buffLength); } // Close the file stream and the Request Stream strm.Close(); fs.Close(); } 

最简单的方法是使用BackgroundWorker并将您的代码放入DoWork事件处理程序中。 并使用BackgroundWorker.ReportProgress报告进度。

基本理念:

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { var ftpWebRequest = (FtpWebRequest)WebRequest.Create("ftp://example.com"); ftpWebRequest.Method = WebRequestMethods.Ftp.UploadFile; using (var inputStream = File.OpenRead(fileName)) using (var outputStream = ftpWebRequest.GetRequestStream()) { var buffer = new byte[1024 * 1024]; int totalReadBytesCount = 0; int readBytesCount; while ((readBytesCount = inputStream.Read(buffer, 0, buffer.Length)) > 0) { outputStream.Write(buffer, 0, readBytesCount); totalReadBytesCount += readBytesCount; var progress = totalReadBytesCount * 100.0 / inputStream.Length; backgroundWorker1.ReportProgress((int)progress); } } } private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { progressBar.Value = e.ProgressPercentage; } 

确保启用了WorkerReportsProgress

 backgroundWorker2.WorkerReportsProgress = true; 

使用BackgroundWorker您还可以轻松实现上传取消。

使用FtpWebRequest和WinForms进度条使用Task类进行FTP上传的简单示例:

 private void button1_Click(object sender, EventArgs e) { // Run Upload on background thread Task.Run(() => Upload()); } private void Upload() { FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip"); request.Credentials = new NetworkCredential("username", "password"); request.Method = WebRequestMethods.Ftp.UploadFile; using (Stream fileStream = File.OpenRead(@"C:\local\path\file.zip")) using (Stream ftpStream = request.GetRequestStream()) { progressBar1.Invoke( (MethodInvoker)delegate { progressBar1.Maximum = (int)fileStream.Length; }); byte[] buffer = new byte[10240]; int read; while ((read = fileStream.Read(buffer, 0, buffer.Length)) > 0) { ftpStream.Write(buffer, 0, read); progressBar1.Invoke( (MethodInvoker)delegate { progressBar1.Value = (int)fileStream.Position; }); } } } 

在此处输入图像描述

核心上传代码基于:
在C#/ .NET中上传和下载二进制文件到/从FTP服务器下载

请参阅BackgroundWorker ,它允许您在GUI仍然响应时运行耗时的任务,并且还提供进度/取消。

使用async / await模式的IProgress接口的可取消方法,利用重叠的I / O(如果可用)。 请参阅KB156932以确定您的方案是否符合条件。 在打开流之前检查取消令牌,否则在传输文件时将其卸载到流的异步方法。

我做了很少的基准测试,但怀疑这只是在发送大文件时才实用。 使用重叠I / O的性能可能会因较小的文件,特别是较小的缓冲区大小而降低。

 public async Task FtpAsync(string sourceFile, Uri destinationUri, string user, SecureString password, IProgress progress, CancellationToken token) { const int bufferSize = 128 * 1024; // 128kb buffer progress.Report(0m); var request = (FtpWebRequest)WebRequest.Create(destinationUri); request.Method = WebRequestMethods.Ftp.UploadFile; request.Credentials = new NetworkCredential(user, password); token.ThrowIfCancellationRequested(); using (var fileStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, true)) { using (var ftpStream = await request.GetRequestStreamAsync()) { var buffer = new byte[bufferSize]; int read; while ((read = await fileStream.ReadAsync(buffer, 0, buffer.Length, token)) > 0) { await ftpStream.WriteAsync(buffer, 0, read, token); var percent = 100m * ((decimal)fileStream.Position / fileStream.Length); progress.Report(percent); } } } var response = (FtpWebResponse)await request.GetResponseAsync(); var success = (int)response.StatusCode >= 200 && (int)response.StatusCode < 300; response.Close(); if (!success) throw new Exception(response.StatusDescription); }