【问题标题】:How can we show progress bar for upload with FtpWebRequest我们如何使用 FtpWebRequest 显示上传进度条
【发布时间】:2011-09-14 12:33:50
【问题描述】:

我正在使用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();
}

【问题讨论】:

    标签: c# winforms ftp progress-bar ftpwebrequest


    【解决方案1】:

    一个简单的使用FtpWebRequest 的FTP 上传示例和使用Task class 的WinForms 进度条:

    private void button1_Click(object sender, EventArgs e)
    {
        // Run Upload on background thread
        Task.Run(() => Upload());
    }
    
    private void Upload()
    {
        string url = "ftp://ftp.example.com/remote/path/file.zip";
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
        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; });
            }
        }
    }
    

    核心上传代码基于:
    Upload and download a file to/from FTP server in C#/.NET

    【讨论】:

      【解决方案2】:

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

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

      public async Task FtpAsync(string sourceFile, Uri destinationUri, string user, SecureString password, IProgress<decimal> 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);
      }
      

      【讨论】:

        【解决方案3】:

        最简单的方法是使用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,您还可以轻松实现上传取消。

        【讨论】:

        • 是的,但是上传 3mb 文件的分辨率不是很好,只显示 23% 53,然后是 100
        • @Afnan Bashir - 您可以根据需要调整缓冲区大小。
        【解决方案4】:

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

        【讨论】:

        • 这是一个仅限链接的边界答案。您应该在此处扩展您的答案以包含尽可能多的信息,并使用该链接仅供参考。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多