FtpWebRequest
を使用してFTPにファイルをアップロードしています。どれだけの状態なのかを示す必要があります。
これまでのところ私のコードは:
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();
}
最も簡単なのは、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
を使用すると、アップロードのキャンセルも簡単に実装できます。
FtpWebRequest
class を使用したWinFormsプログレスバーでTask
を使用したFTPアップロードの簡単な例:
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; });
}
}
}
コアアップロードコードは以下に基づいています。
C#/。NETのFTPサーバーとの間でバイナリファイルをアップロードおよびダウンロードします
非同期/待機パターンのIProgressインターフェイスを使用したキャンセル可能なアプローチで、可能であれば 重複したI/O を利用します。 KB156932 を参照して、シナリオが適切かどうかを判断してください。キャンセルトークンは、ストリームを開く前にチェックされますが、それ以外の場合は、ファイルの転送中にストリームの非同期メソッドにオフロードされます。
私はベンチマークをほとんど行っていませんが、これは大きなファイルを送信する場合にのみ実用的であると思われます。オーバーラップI/Oを使用すると、ファイルが小さくなり、特にバッファサイズが小さくなると、パフォーマンスが低下することがあります。
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 を参照してください。GUIが応答している間に時間のかかるタスクを実行でき、進行状況/キャンセルも提供されます。