读书人

关于断点续传

发布时间: 2012-10-18 13:46:55 作者: rapoo

求助,关于断点续传
最近在做一个能够断点续传的下载器,其中遇到了一个问题
比如要下载的文件大小是100k
那么下载到50k的时候我中断下载,下次续传的时候,下载完成是文件大小为150k
同样,下载到30k中断,续传完成的文件就是130k
用的代码不多,在论坛上面找的,反复核查都没发现问题所在
希望能有大神给指点下迷津,谢了
下面是代码~~~

C# code
class classDownloader    {        private string strURL;  //待下载文件链接        private string strSavePath; //待下载文件存放路径        private long lContentLenth = 0; //文件的大小        private long lStartPos = 0; //文件下载的起始位置        private System.IO.FileStream fs;        private System.IO.Stream ns;        private System.Net.HttpWebRequest request;        private System.Net.WebRequest req;        private const int NBuff = 512;//下载流缓冲池大小        private void SetURL(string temp)    //获取待下载文件链接        {            strURL = temp;        }        private void SetSavePath(string temp)   //获取待下载文件存放路径        {            strSavePath = temp;        }        private void  StartDownload() //开始下载        {            //打开网络连接            try            {               // req = System.Net.HttpWebRequest.Create(strURL);               // req.Method = "HEAD";                 request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(strURL);                 System.Net.WebResponse resp = request.GetResponse();                 long.TryParse(resp.Headers.Get("Content-Length"), out lContentLenth);//获取待下载文件的大小                //判断是新文件或续传文件或已经下好了                if (System.IO.File.Exists(strSavePath))                {                    fs = System.IO.File.OpenWrite(strSavePath);                    lStartPos = fs.Length;                    if (lStartPos >= lContentLenth)                    {                        MessageBox.Show("已经下好了");                        return;                    }                    //lStartPos -= 10240;                    fs.Seek(lStartPos, System.IO.SeekOrigin.Current);                }                else                {                    fs = new System.IO.FileStream(strSavePath, System.IO.FileMode.Create);                    lStartPos = 0;                }                if (lStartPos > 0)                {                    request.AddRange((int)lStartPos);   //设置range值                }                //向服务器请求,获得服务器回应数据流                 ns = request.GetResponse().GetResponseStream();                byte[] nbytes = new byte[NBuff];                int nReadSize = 0;                nReadSize = ns.Read(nbytes, 0, NBuff);                while (nReadSize > 0)                {                    fs.Write(nbytes, 0, nReadSize);                    nReadSize = ns.Read(nbytes, 0, NBuff);                    Program.a.progressBar1.Value = (int)(((float)fs.Length / (float)lContentLenth) * 100);                    int resault = (int)((float)fs.Length / (float)lContentLenth*100);                    Program.a.label2.Text = "已下载" + resault+"%";                    //Program.a.label2.Text = "已下载" + fs.Length + "/" + lContentLenth;                }                //MessageBox.Show("下载完成");            }            catch (Exception ex)            {                MessageBox.Show("下载中出错" + ex.ToString());            }            finally            {                if (!(lStartPos >= lContentLenth))                {                    ns.Close();                    fs.Close();                }                //req.Abort();                request.Abort();            }        }        public void update()        {            classWebRequest webrequest = new classWebRequest();            webrequest.WebReqVer();            /*            DataSet dataset = new DataSet();            DataTable datatable = new DataTable("UpdataContext");            datatable.Columns.Add(new DataColumn ("No.",typeof (int)));            datatable.Columns.Add(new DataColumn ("FileName",typeof (string)));            datatable.Columns.Add(new DataColumn ("Status",typeof (string)));            DataRow datarow;            for (int j = 1; j < webrequest.VerList.Count; j++)            {                datarow = datatable.NewRow();                datarow["No."]=j;                datarow["FileName"]="ZZV" + webrequest .VerList[j]  + ".pcg";                datatable.Rows.Add(datarow);            }            dataset .Tables.Add(datatable);            Program .a.dataGridView1 .DataSource =dataset.Tables ["UpdataContext"];             */            int i = 1;                              while (i < webrequest .VerList .Count  )            {                Program.a.dataGridView1.Rows[i-1].Cells[2].Value ="正在下载中";                SetSavePath("d:\\ZZV" + webrequest .VerList[i]  + ".pcg.dat");                SetURL("http://www.autososcn.com/webservice/soft/zzv" + webrequest .VerList [i]  + ".zip");                StartDownload();                //解压                ZipData.UnZipFile("d:\\ZZV" + webrequest.VerList[i] + ".pcg.dat", "d:\\temp\\");                //释放                classChangeFile.UnPackage("d:\\temp\\ZZV" + webrequest.VerList[i] + ".pcg","e:\\aaaa\\");                Program.a.dataGridView1.Rows[i - 1].Cells[2].Value = "已下载";                i++;            }            MessageBox .Show ("所有更新文件下载完成");        }    } 




[解决办法]
你这边断点续传问题大了,首先,你是直接请求下载,通过获取Content-Length比较文件长度来确定是否要断点续传,这个就有可能出现2个问题,第一、你直接请求,则不是断点续传的请求,而是完整下载的请求。第二文件长度不代表断点处,文件在写入过程中,往往会先申请一段空间,然后写入,如果申请了64K但是只写入了1K,后面部分就产生了空白,需要向前回滚一定字节。
一般下载软件都有产生一个文件下载信息的记录文件,文件下载失败则写入当前断点。
对于http断点续传的请求,应该要这样写:
C# code
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strURL);request.AddRange((int)position);//这里的position就是断点 

读书人网 >C#

热点推荐