Как мы можем показать индикатор выполнения для загрузки с FtpWebRequest
Я загружаю файлы на FTP используя FtpWebRequest
, Мне нужно показать статус, сколько сделано.
Пока что мой код:
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();
}
4 ответа
Самый простой в использовании 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
Вы также можете легко осуществить отмену загрузки.
Тривиальный пример загрузки с использованием FTP FtpWebRequest
с помощью индикатора выполнения WinForms 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; });
}
}
}
Код основной загрузки основан на:
Загрузить и загрузить двоичный файл на / с FTP-сервера в C#/.NET
Поддающийся отмене подход с использованием интерфейса IProgress шаблона async / await, использующий преимущества перекрывающегося ввода-вывода, если он доступен. Обратитесь к KB156932, чтобы определить, подходит ли ваш сценарий. Токен отмены проверяется перед открытием потоков, но в противном случае он выгружается в асинхронные методы потоков во время передачи файла.
Я провел очень мало тестов, но подозреваю, что это практично только при отправке больших файлов. Производительность использования перекрывающихся операций ввода-вывода может ухудшиться при уменьшении размера файлов и, особенно, меньшего размера буфера.
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);
}
Посмотрите BackgroundWorker, он позволяет вам запускать трудоемкую задачу, в то время как графический интерфейс все еще реагирует, а также обеспечивает выполнение / отмену.