Recursive uploading files using FtpWebRequest , BackgroundWorker in C# -
using ftpwebrequest class , assign backgroundworker upload file. , working want upload files directory , sub-directory.
i have created component called - "ftpuploading" in define private void function "ftpuploading_dowork"
and same should calling windows form application... if single file in directory working file if there more 1 file , sub-directory... not work.
private void ftpuploading_dowork(object sender, doworkeventargs e) { backgroundworker bw = sender backgroundworker; ftpsettings ftpdet = e.argument 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, 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; }
//calling function
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)); } }
you check isbusy
after starting aync task, , if it's true
, break loop of is. happening.
removing condition lead error mentioned in comments. should either wait task completed, or implement loop inside ftpuploading_dowork
.
and third (and best) option use task
. task
supports continuewith()
need.
i explain first solution here, because needs little changes on existing code. give glimpse of synchronization process. need polish code further.
you need waithandle
, ftpuploading_dowork
tell recursivedirectory
when finished job. use manualresetevent
matter. once reset
manualresetevent, wait on call waitone
until thread calls set
on same manualresetevent.
so work, add manualresetevent
class:
system.threading.manualresetevent waitforupload = new system.threading.manualresetevent(false);
change first for
inside recursivedirectory
:
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); // case if waithandle set // backgroundworker still busy, // should not take long } }
and change ftpuploading_dowork
:
private void ftpuploading_dowork(object sender, doworkeventargs e) { try { // existing code inside method } { waitforupload.set(); } }
Comments
Post a Comment