Prev: Problem with BinaryFormatter Deserialize method
Next: how best to save dataset to a database file
From: Rich P on 23 Sep 2009 18:19 In my custom ftp app that I am writing for downloading my own .jpg and .mp4 files from my ftp server I have implemented a backgroundworker control where the downloading takes place and a progressbar control for monitoring the progress. I am having a problem with .mp4 files larger than 20 megs (sometimes larger than 23 megs). I pass the int value of the Convert.ToInt32(fileBytesRead * 100 / fileSize); value to the ProgressChanged event and for the .mp4 files larger than 20 megs I get the following message around 75%. Below is the code I use to perform the download: ... 75 75 75 75 A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll 75 75 75 75 -75 -75 -75 -75 ... //this code works fine for files under 20megs in size FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(ftpServer + "/" + fileName); request.Method = WebRequestMethods.Ftp.DownloadFile; request.Credentials = new NetworkCredential(ftpUserID, ftpPassword); request.UsePassive = true; request.UseBinary = true; request.KeepAlive = false; //close the connection when done FtpWebResponse response = (FtpWebResponse)request.GetResponse(); Stream stream = response.GetResponseStream(); int fileBytesRead = 0; int fileSize = Convert.ToInt32(fileSize); int n; byte[] buffer = new byte[4096]; using (Stream streamFile = File.Create(s1[0] + "\\" + fileName)) { int bytesRead; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0) { streamFile.Write(buffer, 0, bytesRead); fileBytesRead += bytesRead; n = Convert.ToInt32(fileBytesRead * 100 / fileSize); backgroundWorker2.ReportProgress(n, "in use"); } } stream.Close(); Any suggestions appreciated what I need to change to accommodate .mp4 files larger than 20-23 megs. Thanks Rich *** Sent via Developersdex http://www.developersdex.com ***
From: Peter Duniho on 23 Sep 2009 18:34 On Wed, 23 Sep 2009 15:19:20 -0700, Rich P <rpng123(a)aol.com> wrote: > In my custom ftp app that I am writing for downloading my own .jpg and > .mp4 files from my ftp server I have implemented a backgroundworker > control where the downloading takes place and a progressbar control for > monitoring the progress. I am having a problem with .mp4 files larger > than 20 megs (sometimes larger than 23 megs). I pass the int value of > the Convert.ToInt32(fileBytesRead * 100 / fileSize); Instead, try "(int)(fileBytesRead / (fileSize / 100));" Calling a method (i.e. Convert.ToInt32) instead of just writing a cast the compiler can deal with is inefficient in any case, even if the result of the calculation weren't already an "int" (and in your example, it is), and multiplying your "fileBytesRead" by 100, you are overflowing the int when the byte count is larger than 2^31 / 100 (i.e. right about 20MB). Also, while you should make the change to avoid the overflow in any case, note that if you should use "long" instead of "int" anyway, otherwise you'll have problems with files larger than 2GB. (Once you change from "int" to "long", then you actually will need the cast to "int"). Finally note that the overflow-proof calculation is susceptible to file sizes _less than_ 100 bytes (you'll get a divide-by-zero). Fortunately, for such small files, progress indication is pointless; you can just not bother doing the calculation at all if "fileSize" is less than 100 (just set the progress to 0 or 100, depending on what user feedback you prefer). Pete
From: Rich P on 23 Sep 2009 18:43 I may have figured this one out. I set int fileBytesRead = 0; to long fileBytesRead = 0; I may have to set a few more params to longs, but I think this is the problem. Rich *** Sent via Developersdex http://www.developersdex.com ***
From: Rich P on 23 Sep 2009 18:53 Nevermind. I fixed it. I had to use a double and convert that to Int32. I guess 23,000,000 * 100 is bigger than an int. Rich *** Sent via Developersdex http://www.developersdex.com ***
From: Peter Duniho on 23 Sep 2009 19:04 On Wed, 23 Sep 2009 15:43:21 -0700, Rich P <rpng123(a)aol.com> wrote: > I may have figured this one out. I set > > int fileBytesRead = 0; > > to > > long fileBytesRead = 0; > > I may have to set a few more params to longs, but I think this is the > problem. That will work fine, until you try to process a file that is more 2^63 / 100 bytes long. Granted, we are quite a ways before it's practical to download a file that large. :) But you'd be surprised at how many years code can survive. The same thing applies to using "double" as to "long", though with slightly different limits. IMHO, it would be better to just avoid the calculation that can overflow in the first place (see my other reply to your post). There will always be limits to how large a file your code can handle, but why make that limit arbitrarily smaller than what the related components (network, file system, etc.) can deal with? Pete
|
Next
|
Last
Pages: 1 2 Prev: Problem with BinaryFormatter Deserialize method Next: how best to save dataset to a database file |