private static async void DownloadUnKownSizeFile(DownloadInfo info, IDownloadManagerListener managerListener) { try { using (var httpClient = CreateHttpClient()) { var response = await httpClient.GetAsync(info.Url, HttpCompletionOption.ResponseHeadersRead, info.CancellationTokenSource.Token); using (var stream = await response.Content.ReadAsStreamAsync()) { var bytes = new byte[_bytesLength]; using ( var fileStream = new FileStream(Path.Combine(info.Url, info.Name), FileMode.Append, FileAccess.Write)) { int writeLength; stream.Position = fileStream.Length; while ((writeLength = (stream.Read(bytes, 0, _bytesLength))) > 0) { if (info.CancellationTokenSource.Token.IsCancellationRequested) { info.DownloadStatus = DownloadStatus.UnDownload; info.Listener.OnDownloadCancled(info); break; } fileStream.Write(bytes, 0, writeLength); info.DownloadSize += writeLength; info.Listener.OnDownloadProgress(info); } fileStream.Flush(); fileStream.Close(); stream.Flush(); stream.Close(); } if (info.DownloadStatus == DownloadStatus.Downloading) { info.DownloadStatus = DownloadStatus.Downloaded; info.Listener.OnDownloadCompleted(info); managerListener.OnDownloadCompleted(info); } } } } catch (Exception ex) { Logger.LogHelper.Error("下载文件出错", ex); info.Exception = ex; info.Message = ex.Message; info.DownloadStatus = DownloadStatus.DownloadFailed; info.Listener.OnDownloadFailed(info); } }
public static bool CanDownload(DownloadInfo downloadInfo, out string msg) { msg = ""; if (string.IsNullOrEmpty(downloadInfo.Url)) { msg = "下载地址不能为空"; return(false); } if (_downloadInfos.Values.Count(o => o.Url == downloadInfo.Url && downloadInfo.DownloadStatus != DownloadStatus.DownloadPause) > 0) { Logger.LogHelper.Info($"当前文件{downloadInfo.Name}({downloadInfo.Name})正在下载"); msg = "文件已经在下载中,请不要重复下载"; return(false); } return(true); }
private static async Task <Tuple <string, long> > GetFileSize(DownloadInfo info) { using (var httpClient = CreateHttpClient()) { httpClient.Timeout = _timeOut; var response = await httpClient.GetAsync(info.Url, HttpCompletionOption.ResponseHeadersRead, info.CancellationTokenSource.Token); var contentLength = response.Content.Headers.ContentLength; if (contentLength == null) { Logger.LogHelper.Info($"下载文件:{info.Name}({info.Url});无法获取文件长度"); return(new Tuple <string, long>(response.Content.Headers.ContentDisposition?.FileName, 0)); } return(new Tuple <string, long>(response.Content.Headers.ContentDisposition?.FileName, contentLength.Value));; } }
private static void MergeFile(DownloadInfo info) { var path = Path.Combine(info.SavePath, info.Name.Replace(".", "")); //这里排序一定要正确,转成数字后排序(字符串会按1 10 11排序,默认10比2小) foreach (var filePath in Directory.GetFiles(path).OrderBy(Path.GetFileNameWithoutExtension)) { var file = Directory.GetParent(path).FullName + @"\" + info.Name; using (var fs = File.Open(file, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) { //int count = 0; //while (count < 20 && Win32.IsOpen(filePath)) //{ // await Task.Delay(200); // count++; //} var bytes = File.ReadAllBytes(filePath); //读取文件到字节数组 fs.Write(bytes, 0, bytes.Length); //写入文件 fs.Flush(); fs.Close(); } //int sequence = 0; //while (sequence < 20 && Win32.IsOpen(filePath)) //{ // await Task.Delay(200); // sequence++; //} if (!Win32.IsOpen(filePath)) { File.Delete(filePath); } } if (!Directory.GetFiles(path).Any()) { Directory.Delete(path); } }
/// <summary> /// 单线程下载 /// </summary> /// <param name="info"></param> /// <param name="managerListener"></param> public static async void DownloadWithSingleThreed(DownloadInfo info, IDownloadManagerListener managerListener) { try { var contentLength = info.FileSize; if (info.FileSize <= 0 || string.IsNullOrEmpty(info.Name)) { var file = await GetFileSize(info); if (string.IsNullOrEmpty(info.Name)) { info.Name = file.Item1; } if (file.Item2 <= 0) { DownloadUnKownSizeFile(info, managerListener); return; } } if (string.IsNullOrEmpty(info.Name)) { info.Name = Guid.NewGuid().ToString(); } info.Listener.OnDownloadStart(info); using (var httpClient = CreateHttpClient()) { if (!Directory.Exists(info.SavePath)) { Directory.CreateDirectory(info.SavePath); } using (var fileStream = new FileStream(Path.Combine(info.SavePath, info.Name), FileMode.Append, FileAccess.Write)) { var bytes = new byte[_bytesLength]; var beginSecond = DateTime.Now.Second; if (fileStream.Length >= contentLength) { info.Listener.OnDownloadCompleted(info); managerListener.OnDownloadCompleted(info); return; } httpClient.DefaultRequestHeaders.Add("Range", "bytes = " + fileStream.Length + " - " + (contentLength - 1)); contentLength -= fileStream.Length; var response = await httpClient.GetAsync(info.Url, info.CancellationTokenSource.Token); using (var stream = await response.Content.ReadAsStreamAsync()) { int writeLength; var readLength = _bytesLength; if (readLength != -1 && contentLength < readLength) { readLength = (int)contentLength; } while ((writeLength = (stream.Read(bytes, 0, readLength))) > 0) { if (info.CancellationTokenSource.Token.IsCancellationRequested) { info.Listener.OnDownloadCancled(info); } fileStream.Write(bytes, 0, writeLength); info.DownloadSize += writeLength; info.Progress = info.DownloadSize / contentLength; if (beginSecond != DateTime.Now.Second) { info.Speed = writeLength / (DateTime.Now.Second - beginSecond) / 1024; } info.Listener.OnDownloadProgress(info); contentLength -= writeLength; if (contentLength <= 0) { info.DownloadStatus = DownloadStatus.Downloaded; info.Listener.OnDownloadCompleted(info); managerListener.OnDownloadCompleted(info); } } stream.Flush(); stream.Close(); } fileStream.Flush(); fileStream.Close(); } } } catch (Exception ex) { Logger.LogHelper.Error("下载文件出错", ex); info.Message = ex.Message; info.Exception = ex; info.DownloadStatus = DownloadStatus.DownloadFailed; info.Listener.OnDownloadFailed(info); managerListener.OnDownloadFailed(info); } }
private static async Task DownloadChunk(DownloadInfo info) { try { var sequence = 1; var path = Path.Combine(info.SavePath, info.Name.Replace(".", "")); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } while (_downloadingFiles[info.Url].DownloadingFiles.Contains($"{info.Name.Split('.')[0]}_{sequence}.temp")) { sequence++; } if (_downloadingFiles[info.Url].FileLength < (sequence - 1) * _oneThreadSize) { return; } string fileName = $"{info.Name.Split('.')[0]}_{sequence}.temp"; _downloadingFiles[info.Url].DownloadingFiles.Add(fileName); using (var httpClient = CreateHttpClient()) { long from = (sequence - 1) * _oneThreadSize; long to = Math.Min(sequence * _oneThreadSize, _downloadingFiles[info.Url].FileLength); using (var fileStream = File.Open(Path.Combine(path, fileName), FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) { from += fileStream.Length; long downloadSize = to - from; if (from < to - 1) { httpClient.DefaultRequestHeaders.Add("Range", $"bytes={from}-{to - 1}"); var response = await httpClient.GetAsync(info.Url, info.CancellationTokenSource.Token); using (var stream = await response.Content.ReadAsStreamAsync()) { var bytes = new byte[_bytesLength]; int writeLength; int readLength = _bytesLength; if (downloadSize != 0 && downloadSize < readLength) { readLength = (int)downloadSize; } while ((writeLength = (stream.Read(bytes, 0, readLength))) > 0) { if (info.CancellationTokenSource.Token.IsCancellationRequested) { info.Listener.OnDownloadCancled(info); } fileStream.Write(bytes, 0, writeLength); downloadSize -= writeLength; info.DownloadSize += writeLength; info.Listener.OnDownloadProgress(info); if (downloadSize != 0 && downloadSize < readLength) { readLength = (int)downloadSize; } if (downloadSize <= 0) { break; } } stream.Flush(); stream.Close(); } } fileStream.Flush(); fileStream.Close(); } } var fileCount = _downloadingFiles.Count(); if (_downloadingFiles[info.Url].FileLength < fileCount * _oneThreadSize) { return; } await DownloadChunk(info); } catch (Exception ex) { Logger.LogHelper.Error("下载文件出错", ex); info.Exception = ex; info.Message = ex.Message; info.DownloadStatus = DownloadStatus.DownloadFailed; info.Listener.OnDownloadFailed(info); info.CancellationTokenSource.Cancel(); } }
public static async void DownloadWithMultiThreed(DownloadInfo info, IDownloadManagerListener managerListener) { try { var contentLength = info.FileSize; if (info.FileSize <= 0 || string.IsNullOrEmpty(info.Name)) { var file = await GetFileSize(info); if (string.IsNullOrEmpty(info.Name)) { info.Name = file.Item1; } if (file.Item2 <= 0) { DownloadUnKownSizeFile(info, managerListener); return; } } if (string.IsNullOrEmpty(info.Name)) { info.Name = Guid.NewGuid().ToString(); } info.Listener.OnDownloadStart(info); var fileInfo = new FileInfo { FileLength = contentLength }; if (_downloadingFiles.ContainsKey(info.Url)) { _downloadingFiles.Remove(info.Url); } _downloadingFiles.Add(info.Url, fileInfo); int taskCount = (int)(_downloadingFiles[info.Url].FileLength / _oneThreadSize); var tasks = new List <Task>(); for (int i = 0; i < _maxThread; i++) { if (taskCount <= 0) { break; } taskCount--; var t = Task.Run(async() => { await DownloadChunk(info); }); tasks.Add(t); } Task.WaitAll(tasks.ToArray()); if (info.DownloadStatus == DownloadStatus.Downloading) { MergeFile(info); info.DownloadStatus = DownloadStatus.Downloaded; info.Listener.OnDownloadCompleted(info); managerListener.OnDownloadCompleted(info); } } catch (Exception ex) { Logger.LogHelper.Error("下载文件出错", ex); if (info.Message == null) { info.Exception = ex; info.Message = ex.Message; } info.DownloadStatus = DownloadStatus.DownloadFailed; info.Listener.OnDownloadFailed(info); managerListener.OnDownloadFailed(info); } }
public static void Pause(DownloadInfo downloadInfo) { }