gpt4 book ai didi

c# - 在 C# 中使用 FtpWebRequest 和 BackgroundWorker 递归上传文件

转载 作者:太空宇宙 更新时间:2023-11-03 16:08:29 26 4
gpt4 key购买 nike

使用 FtpWebRequest 类并分配 BackgroundWorker 上传文件。并正常工作但现在我想从目录及其子目录上传文件。

我创建了一个名为“FtpUploading”的组件,其中定义了 private void 函数“FtpUploading_DoWork”

同样应该从 Windows 窗体应用程序调用...如果目录中有单个文件则工作文件但如果有多个文件和子目录...它将无法工作。

    private void FtpUploading_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
FtpSettings ftpDet = e.Argument as FtpSettings;

string UploadPath = String.Format("{0}/{1}{2}", ftpDet.Host, ftpDet.TargetFolder == "" ? "" : ftpDet.TargetFolder + "/", Path.GetFileName(ftpDet.SourceFile));
if (!UploadPath.ToLower().StartsWith("ftp://"))
UploadPath = "ftp://" + UploadPath;
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(UploadPath);
request.UseBinary = true;
request.UsePassive = ftpDet.Passive;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(ftpDet.Username, ftpDet.Password);

long FileSize = new FileInfo(ftpDet.SourceFile).Length;
string mFileName = new FileInfo(ftpDet.SourceFile).Name;
string FileSizeDescription = GetFileSize(FileSize);
int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
long SentBytes = 0;

byte[] Buffer = new byte[ChunkSize];

using (Stream requestStream = request.GetRequestStream())
{
using (FileStream fs = File.Open(ftpDet.SourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
int BytesRead = fs.Read(Buffer, 0, ChunkSize);
while (BytesRead > 0)
{
try
{
if (bw.CancellationPending)
return;

requestStream.Write(Buffer, 0, BytesRead);
SentBytes += BytesRead;

string SummaryText = String.Format(mFileName + " => Transferred {0} / {1}", GetFileSize(SentBytes), FileSizeDescription);
bw.ReportProgress((int)(((decimal)SentBytes / (decimal)FileSize) * 100), SummaryText);
}
catch (Exception ex)
{
Debug.WriteLine("Exception: " + ex.ToString());
if (NumRetries++ < MaxRetries)
{
fs.Position -= BytesRead;
}
else
{
throw new Exception(String.Format("Error occurred during upload, too many retries. \n{0}", ex.ToString()));
}
}
BytesRead = fs.Read(Buffer, 0, ChunkSize);
}
}
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
System.Diagnostics.Debug.WriteLine(String.Format("Upload File Complete, status {0}", response.StatusDescription));
}


public static string GetFileSize(long numBytes)
{
string fileSize = "";

if (numBytes > 1073741824)
fileSize = String.Format("{0:0.00} Gb", (double)numBytes / 1073741824);
else if (numBytes > 1048576)
fileSize = String.Format("{0:0.00} Mb", (double)numBytes / 1048576);
else
fileSize = String.Format("{0:0} Kb", (double)numBytes / 1024);

if (fileSize == "0 Kb")
fileSize = "1 Kb"; // min.
return fileSize;
}

//调用函数

        private void recursiveDirectory(string dirPath, string uploadPath)
{
string[] files = Directory.GetFiles(dirPath, "*.*");
string[] subDirs = Directory.GetDirectories(dirPath);
foreach (string file in files)
{
if (this.ftpUploading1.IsBusy)
{
// this.ftpUploading1.CancelAsync();
// this.btnFtp.Text = "Upload";
Thread.Sleep(50);
break;
}
else
{
ftpSet.TargetFolder = uploadPath;
ftpSet.SourceFile = file;
this.toolStripProgressBar1.Visible = true;
this.ftpUploading1.RunWorkerAsync(ftpSet);
this.btnFtp.Text = "Cancel";
}
}
foreach (string subDir in subDirs)
{
ftpClient.createDirectory(uploadPath + "/" + Path.GetFileName(subDir));
recursiveDirectory(subDir, uploadPath + "/" + Path.GetFileName(subDir));
}
}

最佳答案

您在启动 ync 任务后立即检查 IsBusy,如果它是 true,您将打破几乎总是如此的循环。这是怎么回事。

删除该条件将导致您在评论中提到的错误。因此,您应该等待任务完成,或者在 FtpUploading_DoWork 中实现一个循环。

第三个(也是最好的)选项是使用任务Task 支持 ContinueWith(),这正是您所需要的。

我将在这里解释第一个解决方案,因为它只需要对您现有的代码进行很少的更改。此外,这只是为了让您大致了解同步过程。您可能需要进一步完善代码。

您需要一个 WaitHandle,以便 FtpUploading_DoWork 告诉 recursiveDirectory 它何时完成其工作。为此,我们将使用 ManualResetEvent。一旦您 Reset ManualResetEvent,它将等待对 WaitOne 的调用,直到另一个线程在同一个 ManualResetEvent 上调用 Set

回到工作中,将 ManualResetEvent 添加到您的类中:

System.Threading.ManualResetEvent waitForUpload = new 
System.Threading.ManualResetEvent(false);

更改 recursiveDirectory 中的第一个 for:

    foreach (string file in files)
{
ftpSet.TargetFolder = uploadPath;
ftpSet.SourceFile = file;
this.toolStripProgressBar1.Visible = true;

waitForUpload.Reset();
this.ftpUploading1.RunWorkerAsync(ftpSet);
this.btnFtp.Text = "Cancel";

waitForUpload.WaitOne();
while (this.ftpUploading1.IsBusy)
{
Thread.Sleep(100); // This is for the case if the WaitHandle is Set
// but the BackgroundWorker is still busy,
// which should not take so long
}
}

并更改 FtpUploading_DoWork:

private void FtpUploading_DoWork(object sender, DoWorkEventArgs e)
{
try
{
// Existing code inside the method
}
finally
{
waitForUpload.Set();
}
}

关于c# - 在 C# 中使用 FtpWebRequest 和 BackgroundWorker 递归上传文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18440473/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com