Comment Pouvons-nous Afficher la barre de progression pour upload avec FtpWebRequest

je télécharge des fichiers vers ftp en utilisant FtpWebRequest . Je dois montrer le statut que combien est fait.

Jusqu'à présent mon code est:

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();
}
24
demandé sur Martin Prikryl 2011-06-14 12:34:34

4 réponses

le plus simple est d'utiliser BackgroundWorker et de mettre votre code dans DoWork event handler. Et signalez les progrès avec BackgroundWorker.ReportProgress .

L'idée de base:

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

assurez-vous que WorkerReportsProgress est activé

backgroundWorker2.WorkerReportsProgress = true;

avec BackgroundWorker vous pouvez également facilement mettre en œuvre l'annulation de téléchargement.

35
répondu Alex Aza 2014-05-21 11:40:34

un exemple trivial de téléchargement FTP utilisant FtpWebRequest avec la barre de progression WinForms utilisant Task classe :

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

enter image description here

le code de téléchargement de base est basé sur:

télécharger un fichier binaire depuis/vers le serveur FTP dans C# / .NET

2
répondu Martin Prikryl 2018-08-20 18:15:21

voir BackgroundWorker , il vous permet d'exécuter une tâche fastidieuse alors que l'interface graphique est encore réactive et fournit également progression/annulation.

0
répondu Guillaume 2011-06-14 08:40:28

une approche annulable utilisant l'interface IProgress de async/wait pattern, en profitant de chevauchant I/O si disponible. Consultez la section KB156932 pour déterminer si votre scénario est admissible. Le token d'annulation est vérifié avant d'ouvrir les flux, mais sinon est déchargé dans les méthodes async des flux pendant que le fichier est transféré.

j'ai fait très peu de benchmarking, pratique lors de l'envoi de fichiers volumineux. La performance de l'utilisation des entrées-sorties superposées peut se dégrader avec des fichiers plus petits et surtout des tailles de tampon plus petites.

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);
}
0
répondu RMart 2018-01-26 20:10:48