 <p>Your math problem is right here:</p> <pre><code> writeStream.Write(buffer, 0, bytesRead); bytesRead = responseStream.Read(buffer, 0, Length); var progress = bytesRead * 100.0 / writeStream.Length; bw.ReportProgress((int)progress,SummaryText); </code></pre> <p>The return value from <code>responseStream.Read</code> is the number of bytes you read <em>in that one read</em>. It's not the total number of bytes read since you started reading from the file.</p> <p>Also, dividing the number of bytes read by the total number written (i.e. <code>writeStream.Length</code>) isn't telling you anything useful.</p> <p>If you want to update a progress bar, you have to know how many total bytes there are in the file, and how many total bytes you've read up to this point. So if the file is 1,000,000 bytes long, and you've read 450,000 bytes <em>total</em>, the progress would be 45% (i.e. 450000/1000000).</p> <p>In your code, you have to get the file size from the FTP server. That's the total number of bytes you're going to download. Then you need keep track of how many bytes you've read up to this point. The basic idea is:</p> <pre><code>int totalBytesToBeRead = ??; // somehow get length. responseStream.Length doesn't work. int totalBytesRead = 0; int bytesRead = -1; while (bytesRead != 0) { bytesRead = responseStream.Read(...); // now add to the total totalBytesRead += bytesRead; var progress = totalBytesRead * 100.0 / totalBytesToRead; } </code></pre> <h2>Update</h2> <p>The problem appears to be that <code>FtpWebRequest</code> doesn't supply a <code>ContentLength</code>, so you need some other way to get the length. The only thing that comes to mind is to request the length up front by doing a separate <code>FtpWebRequest</code> with the <code>GetFileSize</code> method. See <a href="http://stackoverflow.com/questions/4175874/get-file-size-on-an-ftp-in-c-sharp">Get File Size On An FTP in C#</a> for an example.</p>