c# - ¿Cómo podemos mostrar la barra de progreso para cargar con FtpWebRequest?
winforms progress-bar (4)
Lo más fácil es usar BackgroundWorker
y poner tu código en el controlador de eventos DoWork
. 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 WorkerReportsProgress
esté habilitado
backgroundWorker2.WorkerReportsProgress = true;
Con BackgroundWorker
también puede implementar fácilmente la cancelación de carga.
Estoy cargando archivos a ftp usando FtpWebRequest
. Necesito mostrar el estado de cuánto se hace.
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();
}
Un ejemplo trivial de carga FTP utilizando FtpWebRequest
con la barra de progreso de WinForms usando Task
clase Task
:
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; });
}
}
}
El código de carga central está basado en:
Cargue y descargue un archivo binario a / desde el servidor FTP en C # /. NET
Un enfoque cancelable utilizando la interfaz IProgress del patrón async / await, aprovechando las E / S superpuestas, si están disponibles. Consulte KB156932 para determinar si su escenario 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);
}
Vea BackgroundWorker , le permite ejecutar una tarea que consume tiempo mientras la GUI sigue respondiendo y también proporciona progreso / cancelación.