public const int MaxLength = 104857600; //100M private const string DefaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"; public string Url { get; set; } //下载链接 public string SavePath { get; set; } //保存的完整路径 public long ContentLength { get; private set; } //本次下载的总长度,并非文件总长度 private int unitDownloadLength = MaxLength; bool isStop; private int Offset { get; set; } private WebResponse Response; HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url); if (Url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CertificateValidationCallback); req.ProtocolVersion = HttpVersion.Version11; req.UserAgent = DefaultUserAgent; } if(RecievedSize > 0) req.AddRange(RecievedSize); Response = (HttpWebResponse)req.GetResponse(); using (Stream stream = Response.GetResponseStream()) { if (State == DownloadState.Stoping) return; //判断停止 using (FileStream fs = new FileStream(SavePath, FileMode.Create, FileAccess.Write)) { using (BinaryReader br = new BinaryReader(stream)) { byte[] b = new byte[MaxLength]; while (!isStop && (Offset = br.Read(b, 0, (unitDownloadLength = unitDownloadLength > ContentLength - Offset ? (int)(ContentLength - Offset) : unitDownloadLength))) > 0) //offset等于0时完成下载 { fs.Write(b, 0, Offset); b = new byte[MaxLength]; RecievedSize += Offset; ProgressChanged?.Invoke(null, new DownloadEventArgs(this)); Thread.Sleep(50); } } } }
每次br.read()只read出4096个字节,大概10多次就出一次12288字节,无论我怎么设置单次读取长度都会一直这样
你看下http响应中有没有chunked标志,其次你那个byte数组用的姿势不对,没必要再循环中重新实例化,只需要在最后写到fs中告知其offset和count即可,这样开销会小很多的。
没有chunked标志,byte数组因为每次读取的的长度可能不一样,如果不重新实例化,那么可能会影响下次读取的byte数组
@HotSky: 读取的长度是看BinaryReader返回值,你byte数组在这块是做个buffer而已,你前面已经申明了足够大的空间,在每次写入底层文件时只是通过Write方法告知这块是从这个buffer区域中的哪儿开始读取多少
@Daniel Cai: OK,谢谢!我发现我速度慢是因为用了睡眠-_-||