c# - Extending a custom resumable download class -
i have event handler named downloadprogresschanged in download class. takes 4 arguments through downloadprogresschangedeventargs class, bytesreceived, totalbytestoreceive, progresspercentage & currentspeed.
i'm able download , resume files. stop them too. adding data needeed the downloadprogresseventargs making me confused. main problem don't know info needed bytesreceived argument is. can point me in right direction?
public class download { public event eventhandler<downloadprogresschangedeventargs> downloadprogresschanged; public event eventhandler downloadcompleted; public bool stop = true; // default stop true // add option current downloaded size // add option current download speed public void downloadfile(string downloadlink, string path) { stop = false; // set bool false, everytime method called long existinglength = 0; filestream savefilestream; if (file.exists(path)) { fileinfo fileinfo = new fileinfo(path); existinglength = fileinfo.length; } if (existinglength > 0) savefilestream = new filestream(path, filemode.append, fileaccess.write, fileshare.readwrite); else savefilestream = new filestream(path, filemode.create, fileaccess.write, fileshare.readwrite); var request = (httpwebrequest)httpwebrequest.create(downloadlink); request.addrange((int)existinglength); try { using (var response = (httpwebresponse)request.getresponse()) { long filesize = existinglength + response.contentlength; //response.contentlength gives me size remaining downloaded using (var stream = response.getresponsestream()) { byte[] downbuffer = new byte[1024 * 1000]; int bytesize; var sw = new stopwatch(); while ((bytesize = stream.read(downbuffer, 0, downbuffer.length)) > 0) { savefilestream.write(downbuffer, 0, bytesize); var args = new downloadprogresschangedeventargs(); //args.bytesreceived = ; args.totalbytestoreceive = filesize; args.progresspercentage = (bytesize / (int)filesize) * 100; //args.currentspeed = ; ondownloadprogresschanged(args); if (stop == true) break; } } } } catch (webexception e) { string filename = system.io.path.getfilename(path); system.windows.messagebox.show(e.message, filename); savefilestream.dispose(); //dispose filestream return; //not needed because last line of method, let's keep here } } public void stopdownload() { stop = true; } protected virtual void ondownloadprogresschanged(downloadprogresschangedeventargs e) { eventhandler<downloadprogresschangedeventargs> handler = downloadprogresschanged; if (handler != null) { handler(this, e); } } protected virtual void ondownloadcompleted(eventargs e) { eventhandler handler = downloadcompleted; if (handler != null) { handler(this, e); } } } public class downloadprogresschangedeventargs : eventargs { public long bytesreceived { get; set; } public long totalbytestoreceive { get; set; } public int progresspercentage { get; set; } public double currentspeed { get; set; } }
also bytesize doesn't change @ all. stays same throughout, reason.
here's awesome bug-free working resumable download class quite few improvements:
public class download { public event eventhandler<downloadstatuschangedeventargs> downloadstatuschanged; public event eventhandler<downloadprogresschangedeventargs> downloadprogresschanged; public event eventhandler downloadcompleted; public bool stop = true; // default stop true public void downloadfile(string downloadlink, string path) { stop = false; // set bool false, everytime method called long existinglength = 0; filestream savefilestream; if (file.exists(path)) { fileinfo fileinfo = new fileinfo(path); existinglength = fileinfo.length; } if (existinglength > 0) savefilestream = new filestream(path, filemode.append, fileaccess.write, fileshare.readwrite); else savefilestream = new filestream(path, filemode.create, fileaccess.write, fileshare.readwrite); var request = (httpwebrequest)httpwebrequest.create(downloadlink); request.proxy = null; request.addrange(existinglength); try { using (var response = (httpwebresponse)request.getresponse()) { long filesize = existinglength + response.contentlength; //response.contentlength gives me size remaining downloaded bool downloadresumable; // need sending empty progress if ((int)response.statuscode == 206) { console.writeline("resumable"); var downloadstatusargs = new downloadstatuschangedeventargs(); downloadresumable = true; downloadstatusargs.resumesupported = downloadresumable; ondownloadstatuschanged(downloadstatusargs); } else // server supports partial content lose ability send partial content(weird behavior) , download lose resumability { console.writeline("resume not supported"); existinglength = 0; var downloadstatusargs = new downloadstatuschangedeventargs(); downloadresumable = false; downloadstatusargs.resumesupported = downloadresumable; ondownloadstatuschanged(downloadstatusargs); // restart downloading file beginning because isn't resumable // if isn't done, method downloads file beginning , starts writing after half downloaded file, increasing filesize , corrupting downloaded file savefilestream.dispose(); // dispose object free next operation file.writealltext(path, string.empty); // clear contents of half downloaded file can't resumed savefilestream = savefilestream = new filestream(path, filemode.append, fileaccess.write, fileshare.readwrite); // reopen writing } using (var stream = response.getresponsestream()) { byte[] downbuffer = new byte[4096]; int bytesize = 0; long totalreceived = bytesize + existinglength; var sw = new stopwatch(); sw.start(); while ((bytesize = stream.read(downbuffer, 0, downbuffer.length)) > 0) { savefilestream.write(downbuffer, 0, bytesize); totalreceived += bytesize; var args = new downloadprogresschangedeventargs(); args.bytesreceived = totalreceived; args.totalbytestoreceive = filesize; float currentspeed = totalreceived / (float)sw.elapsed.totalseconds; args.currentspeed = currentspeed; if (downloadresumable == true) { args.progresspercentage = ((float)totalreceived / (float)filesize) * 100; long bytesremainingtobereceived = filesize - totalreceived; args.timeleft = (long)(bytesremainingtobereceived / currentspeed); } else { //args.progresspercentage = unknown; //args.timeleft = unknown; } ondownloadprogresschanged(args); if (stop == true) return; } sw.stop(); } } var completedargs = new eventargs(); ondownloadcompleted(completedargs); savefilestream.dispose(); } catch (webexception e) { string filename = system.io.path.getfilename(path); console.writeline(e.message); savefilestream.dispose(); return; //not needed because last line of method, let's keep here } } public void stopdownload() { stop = true; } protected virtual void ondownloadstatuschanged(downloadstatuschangedeventargs e) { eventhandler<downloadstatuschangedeventargs> handler = downloadstatuschanged; if (handler != null) { handler(this, e); } } protected virtual void ondownloadprogresschanged(downloadprogresschangedeventargs e) { eventhandler<downloadprogresschangedeventargs> handler = downloadprogresschanged; if (handler != null) { handler(this, e); } } protected virtual void ondownloadcompleted(eventargs e) { eventhandler handler = downloadcompleted; if (handler != null) { handler(this, e); } } } public class downloadstatuschangedeventargs : eventargs { public bool resumesupported { get; set; } } public class downloadprogresschangedeventargs : eventargs { public long bytesreceived { get; set; } public long totalbytestoreceive { get; set; } public float progresspercentage { get; set; } public float currentspeed { get; set; } // in bytes public long timeleft { get; set; } // in seconds }
the currentspeed calculation isn't super accurate because needs time become accurate. better way find out how bandwidth application using @ given time. sadly, fail if you're downloading multiple files @ same time.
Comments
Post a Comment