2011-06-14 13 views
23

Estoy cargando archivos a ftp usando FtpWebRequest. Necesito mostrar el estado de cuánto se hace.¿Cómo podemos mostrar la barra de progreso para cargar con FtpWebRequest

Hasta ahora mi código es:

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

Respuesta

35

Lo más fácil es utilizar BackgroundWorker y poner su código en DoWork controlador de eventos. E informe el progreso con BackgroundWorker.ReportProgress.

La idea básica:

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

Asegúrese de que está activada WorkerReportsProgress

backgroundWorker2.WorkerReportsProgress = true; 

Con BackgroundWorker también se puede implementar fácilmente la cancelación de carga.

+0

Si pero reslution no es tan bueno de carga de archivos 3Mb mostró que sólo el 23% y luego 53 100 –

+2

@Afnan Bashir - se puede ajustar el tamaño del búfer a sus necesidades. –

+0

¡Genial! Pero, ¿no deberías cerrar 'inputStream' y' outputStream' también? – ocramot

0

, vea BackgroundWorker, le permite ejecutar una tarea que consume tiempo mientras la GUI sigue respondiendo y también proporciona progreso/cancelación.

+3

Esta es una respuesta limítrofe solo de enlace. Debería ampliar su respuesta para incluir tanta información aquí, y usar el enlace solo como referencia. – gunr2171

1

Un ejemplo trivial de carga FTP usando FtpWebRequest con WinForms barra de progreso usando 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; }); 
     } 
    } 
} 

enter image description here

El código de carga de núcleo se basa en:
Upload and download a binary file to/from FTP server in C#/.NET

0

Un enfoque cancellable usando la interfaz IProgress del patrón async/await, aprovechando overlapped I/O si está disponible. Consulte KB156932 para determinar si su situación califica. El token de cancelación se verifica antes de abrir las transmisiones, pero de lo contrario se descarga a los métodos asíncronos de las transmisiones mientras se está transfiriendo el archivo.

He hecho muy pocas evaluaciones comparativas, pero sospecho que esto solo es práctico cuando se envían archivos de gran tamaño. El rendimiento del uso de E/S superpuestas puede degradarse con archivos más pequeños y especialmente con tamaños de búfer más pequeños.

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