public DownloaderResult Download(Uri url, DownloaderOptions options) { var head = CreateRequest(url, options); head.Method = "HEAD"; var headResponse = (HttpWebResponse)head.GetResponse(); headResponse.Close(); if (this.IsRedirect(headResponse)) { var target = headResponse.Headers[HttpResponseHeader.Location]; if (target.IsNullOrEmpty()) throw new Exception("Response is a redirect, but location header was not set."); return Download(new Uri(target), options); } if (headResponse.StatusCode != HttpStatusCode.OK) throw new NotSupportedException(string.Format("HEAD request returned a response code {0}: {1} that is currently not supported.", headResponse.StatusCode, headResponse.StatusDescription)); while (true) { try { return Download(url, headResponse, options); } catch (DownloadException ex) { this.logger.LogError("Download error {0}, retrying.", ex.Message); } } }
private static HttpWebRequest CreateRequest(Uri url, DownloaderOptions options) { var request = (HttpWebRequest)WebRequest.Create(url); request.Credentials = options.Credentials; request.AllowAutoRedirect = false; return request; }
private DownloaderResult Download(Uri url, HttpWebResponse headResponse, DownloaderOptions options) { var fullLength = headResponse.ContentLength; var fileName = GetFileName(headResponse); var file = this.mapPath(url, fileName); file.Directory.Create(); logger.LogMessage("-> {0}", file.FullName); var get = CreateRequest(url, options); get.Method = "GET"; var lengthDownloadedBefore = 0L; var fileMode = FileMode.Append; if (file.Exists && file.Length > 0) { if (file.Length == fullLength) { this.logger.LogMessage("File is already fully downloaded."); return new DownloaderResult(url, file, headResponse.ContentType); } if (file.Length < fullLength) { this.logger.LogMessage("File already exists, requesting range {0}-{1}.", file.Length, headResponse.ContentLength); get.AddRange(file.Length, fullLength); lengthDownloadedBefore = file.Length; } else if (fullLength <= 0) { this.logger.LogWarning("File already exists, but server did not provide length, so it will be fully redownloaded."); fileMode = FileMode.Create; } else { this.logger.LogWarning("File already exists, but it is larger than file on server, so it will be fully redownloaded. "); fileMode = FileMode.Create; } } var response = get.GetResponse(); var downloadedTotal = 0L; using (response) using (var fileStream = file.Open(fileMode, FileAccess.Write, FileShare.Read)) using (var webStream = response.GetResponseStream()) { var buffer = new byte[1024]; var time = new Stopwatch(); time.Start(); while (true) { int count; try { count = webStream.Read(buffer, 0, buffer.Length); } catch (IOException ex) { throw new DownloadException(ex.Message, ex); } if (count == 0) break; downloadedTotal += count; fileStream.Write(buffer, 0, count); options.ReportProgress(new DownloaderProgress { File = file, BytesDownloadedBefore = lengthDownloadedBefore, BytesDownloaded = downloadedTotal, BytesTotal = fullLength, TimeElapsed = time.Elapsed }); } } this.logger.LogMessage("Download completed."); var contentType = new ContentType(headResponse.ContentType); return new DownloaderResult(url, file, contentType.MediaType); }