How can we show progress bar for upload with FtpWebRequest

|▌冷眼眸甩不掉的悲伤 提交于 2019-11-26 04:46:04

问题


I am uploading files to ftp using FtpWebRequest. I need to show the status that how much is done.

So far my code is:

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();
}

回答1:


The easiest is to use BackgroundWorker and put your code into DoWork event handler. And report progress with BackgroundWorker.ReportProgress.

The basic idea:

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;
}

Make sure WorkerReportsProgress is enabled

backgroundWorker2.WorkerReportsProgress = true;

With BackgroundWorker you can also easily implement upload cancellation.




回答2:


A trivial example of FTP upload using FtpWebRequest with WinForms progress bar using Task class:

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; });
        }
    }
}

The core upload code is based on:
Upload and download a binary file to/from FTP server in C#/.NET




回答3:


See BackgroundWorker, it allows you to run a time consuming task while the GUI still is responsive and also provides progress/cancellation.




回答4:


A cancellable approach using the async/await pattern's IProgress interface, taking advantage of overlapped I/O if available. Refer to KB156932 to determine if your scenario qualifies. The cancellation token is checked before opening the streams, but otherwise is offloaded to the streams' async methods while the file is being transferred.

I have done very little benchmarking, but suspect this is only practical when sending large files. The performance of using overlapped I/O may degrade with smaller files and especially smaller buffer sizes.

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);
}


来源:https://stackoverflow.com/questions/6341024/how-can-we-show-progress-bar-for-upload-with-ftpwebrequest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!