private void FromReaderToFile(StreamReader src, FileStream dest, ref DownloaderMetric metric, ref Stopwatch stopwatch, CancellationToken ct) { var buffer = new byte[32 * 1024]; int bytesRead; while ((bytesRead = src.BaseStream.Read(buffer, 0, buffer.Length)) > 0) { if (ct.IsCancellationRequested) { dest.Flush(true); dest.Close(); dest.Dispose(); return; } dest.Write(buffer, 0, bytesRead); metric.DownloadedBytes += bytesRead; metric.ElapsedTime = stopwatch.Elapsed; OnDownloading?.Invoke(metric); } OnDownloadCompleted?.Invoke(metric); dest.Flush(true); dest.Close(); dest.Dispose(); }
internal byte[] FromReaderToStream(StreamReader sr, Stream destinationStream, ref DownloadMetric metric, ref Stopwatch stopwatch, ref long?length, CancellationToken ct) { //int kb = metric.Speed > Globals.PageSize ? (int)metric.Speed : Globals.PageSize; int kb = 1024 * 65; int toDownload = kb; var buffer = new byte[toDownload]; int bytesRead; while ((bytesRead = sr.BaseStream.Read(buffer, 0, buffer.Length)) > 0) { // Poll on this property if you have to do // other cleanup before throwing. if (ct.IsCancellationRequested) { // Clean up here, then... destinationStream.SetLength(0); destinationStream.Close(); if (destinationStream is FileStream) { var fs = destinationStream as FileStream; if (File.Exists(fs.Name)) { File.Delete(fs.Name); } } ct.ThrowIfCancellationRequested(); } destinationStream.Write(buffer, 0, bytesRead); metric.DownloadedBytes += bytesRead; metric.ElapsedTime = stopwatch.Elapsed; OnDownloading?.Invoke(metric); length -= bytesRead; toDownload = length >= kb ? kb : (int)length; buffer = new byte[toDownload]; } stopwatch.Stop(); DownloadTrace.Invoke("Download finished!"); DownloadTrace.Invoke("Returning results..."); //DownloadCompleted?.Invoke(metric, destinationStream); //stopwatch.Reset(); if (destinationStream is MemoryStream) { return(((MemoryStream)destinationStream).ToArray()); } else { destinationStream.Flush(); destinationStream.Close(); destinationStream.Dispose(); return(null); } }
private Task StartSpeedControllerAsync() { return(Task.Factory.StartNew(async() => { _logger.LogInformation($"任务 {Id} 速度控制器启动"); bool @break = false; MemoryMappedFile mmf = MmfSignal ? MemoryMappedFile.CreateFromFile(Id, FileMode.OpenOrCreate, null, 4, MemoryMappedFileAccess.ReadWrite) : null; using (var accessor = mmf?.CreateViewAccessor()) { accessor?.Write(0, false); accessor?.Flush(); while (!@break) { Thread.Sleep(_speedControllerInterval); switch (Status) { case Status.Running: { try { var requests = _scheduler.Dequeue(Id, _dequeueBatchCount); foreach (var request in requests) { OnDownloading?.Invoke(request); } if (requests.Length > 0) { await _downloadService.EnqueueRequests(Id, requests); } } catch (Exception e) { _logger.LogError($"速度控制器运转失败: {e}"); } break; } case Status.Paused: { _logger.LogInformation($"任务 {Id} 速度控制器暂停"); break; } case Status.Exiting: case Status.Exited: { @break = true; break; } } if (accessor != null && accessor.ReadBoolean(0)) { Exit(); break; } } } _logger.LogInformation($"任务 {Id} 速度控制器退出"); })); }
public async Task DownloadAsync(string savePath) { _downloadTask = new Task(async() => { using (var ms = new MemoryStream()) { try { var request = WebRequest.Create(this.Url) as HttpWebRequest; if (request == null) { // todo throw new Exception(); } request.Timeout = 30000; request.UserAgent = "ozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"; var response = await request.GetResponseAsync().ConfigureAwait(false) as HttpWebResponse; if (response == null) { // todo throw new Exception(); } using (var responseStream = response.GetResponseStream()) { if (responseStream == null) { // todo throw new Exception(); } var fileSize = response.ContentLength; OnStartDownloading?.Invoke(fileSize); var bArr = new byte[1024]; var size = responseStream.Read(bArr, 0, bArr.Length); long totalSize = 0; long lastSize = 0; long speed = 0; _ = Task.Run(() => { bool isFinished = false; OnFinishDownloading += () => { isFinished = true; }; const int interval = 500; const int ratio = 1000 / interval; while (!isFinished && !_cts.IsCancellationRequested) { speed = (totalSize - lastSize) * ratio; lastSize = totalSize; Thread.Sleep(interval); } }); while (size > 0) { if (_cts.IsCancellationRequested) { Logger.Info(@"Download canceled."); return; } totalSize += size; ms.Write(bArr, 0, size); size = responseStream.Read(bArr, 0, (int)bArr.Length); OnDownloading?.Invoke(fileSize, totalSize, speed); } var dir = new FileInfo(savePath).Directory; if (!dir.Exists) { dir.Create(); } using (var fs = new FileStream(savePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) { fs.Write(ms.GetBuffer(), 0, (int)ms.Length); } OnFinishDownloading?.Invoke(); } } catch (WebException ex) { if (ex.InnerException is SocketException) { Logger.Error(@"Connection error. Target URI: {0}", Url); throw; } if (ex.Status == WebExceptionStatus.Timeout) { Logger.Error(@"Connection timed out. Target URI: {0}", Url); throw; } throw; } } }); _downloadTask.Start(); await Task.WhenAll(_downloadTask).ConfigureAwait(false); }
public IEnumerator Start(bool resume = false) { Debug.LogFormat("[WebFileDownloader] Start :{0}", this.url); var headRequest = UnityWebRequest.Head(url); yield return(headRequest.SendWebRequest()); //Debug.LogError("HeadRequest Error:" + headRequest.isNetworkError); if (headRequest.isNetworkError) { if (OnError != null) { OnError(this); } } else { string len = headRequest.GetResponseHeader("Content-Length"); Debug.Log("---------------------------获得长度:" + len); if (string.IsNullOrEmpty(len)) { // Debug.Log(" 下载出错:" + len); if (OnError != null) { OnError(this); } } else { var totalLength = long.Parse(len); if (!Directory.Exists(filePath)) { Directory.CreateDirectory(filePath); } string fileName = Path.GetFileName(this.url); string filePath2 = filePath + "/" + fileName; string tempFilePath = filePath2 + EXTAINSION_NAME; tempFilePath = tempFilePath.Replace("\\", "/"); filePath2 = filePath2.Replace("\\", "/"); string dir = Path.GetDirectoryName(filePath2); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } long lastLen = 0; float _progress = 0; using (FileStream stream = new FileStream(tempFilePath, FileMode.OpenOrCreate, FileAccess.Write)) { var streamLength = stream.Length; lastLen = streamLength; if (!resume) { streamLength = 0; } if (streamLength < totalLength) { stream.Seek(streamLength, SeekOrigin.Current); } UnityWebRequest request = UnityWebRequest.Get(this.url); request.SetRequestHeader("Range", "bytes=" + streamLength + "-" + totalLength); request.SendWebRequest(); error = ""; int offset = 0; while (true) { if (request.isNetworkError) { long code = request.responseCode; // Debug.LogFormat("[WebFileDownloader] Error:{0}", code); error = request.error + ",responeseCode:" + request.responseCode; break; } byte[] data = request.downloadHandler.data; int length = data.Length - offset; stream.Write(data, offset, length); offset += length; streamLength += length; _progress = (float)streamLength / (float)totalLength; float val = (float)(streamLength + lastLen); progress = val / totalLength; //Debug.LogFormat("val:{0}, totalLength:{1} ,streamLength:{2} ,lastLen:{3} ===当前进度:{4} 实际progress:{5}", // val, totalLength, streamLength, lastLen, progress, _progress); if (OnDownloading != null) { OnDownloading.Invoke(this); } if (_progress >= 1) { break; } yield return(0); } netDatas = request.downloadHandler.data; headRequest.Dispose(); request.downloadHandler.Dispose(); request = null; stream.Close(); } if (string.IsNullOrEmpty(error)) { if (File.Exists(tempFilePath)) { ////Debug.Log("开始删除临时文件:"+ tempFilePath); if (File.Exists(filePath2)) { File.Delete(filePath2); } File.Move(tempFilePath, filePath2); //Debug.LogFormat("存入本地文件地址:{0}", filePath2); } //Debug.Log(" 下载完成"); if (OnComplete != null) { OnComplete.Invoke(this); } } else { //Debug.Log(" 下载出错"); if (OnError != null) { OnError(this); } } } } }
/// <summary> /// Http方式下载文件 /// </summary> /// <param name="url">http地址</param> /// <param name="localfile">本地文件</param> /// <returns></returns> public bool Download(string url, string localfile) { Url = url; SaveFilePath = localfile; long startPosition = 0; // 上次下载的文件起始位置 FileStream writeStream = null; // 写入本地文件流对象 try { // 判断要下载的文件夹是否存在 if (File.Exists(localfile)) { writeStream = File.OpenWrite(localfile); // 存在则打开要下载的文件 startPosition = writeStream.Length; // 获取已经下载的长度 writeStream.Seek(startPosition, SeekOrigin.Current); // 本地文件写入位置定位 } else { writeStream = new FileStream(localfile, FileMode.Create);// 文件不保存创建一个文件 startPosition = 0; } HttpWebRequest myRequest = (HttpWebRequest)HttpWebRequest.Create(url);// 打开网络连接 if (startPosition > 0) { myRequest.AddRange((int)startPosition);// 设置Range值,与上面的writeStream.Seek用意相同,是为了定义远程文件读取位置 } var myResponse = (HttpWebResponse)myRequest.GetResponse(); FileTotalBytes = myResponse.ContentLength; FileDownloadedBytes = startPosition; Stream readStream = myRequest.GetResponse().GetResponseStream(); // 向服务器请求,获得服务器的回应数据流 byte[] btArray = new byte[512]; // 定义一个字节数据,用来向readStream读取内容和向writeStream写入内容 int contentSize = readStream.Read(btArray, 0, btArray.Length); // 向远程文件读第一次 IsRunning = true; while (contentSize > 0)// 如果读取长度大于零则继续读 { if (_isStop) { break; } writeStream.Write(btArray, 0, contentSize);// 写入本地文件 FileDownloadedBytes += contentSize; OnDownloading?.Invoke(this); contentSize = readStream.Read(btArray, 0, btArray.Length);// 继续向远程文件读取 } //关闭流 writeStream.Close(); readStream.Close(); IsDownloadSuccess = true; //返回true下载成功 } catch (Exception e) { Logger.Error(e, logger); if (writeStream != null) { writeStream.Close(); } IsDownloadSuccess = false; //返回false下载失败 } IsRunning = false; OnDownloadFinished?.Invoke(this); return(IsDownloadSuccess); }