/// <summary> /// Download a single file or directory. /// </summary> void DownloadDirectoryOrFile(FTPFileSystem fileSystem, string localPath) { // Download the file directly. if (!fileSystem.IsDirectory) { DownloadFile(fileSystem, localPath); } // Download a directory. else { // Construct the directory Path. string directoryPath = localPath + "\\" + fileSystem.Name; if (!Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } // Get the sub directories and files. var subDirectoriesAndFiles = this.manager.GetSubDirectoriesAndFiles(fileSystem.Url); // Download the files in the folder and sub directories. foreach (var subFile in subDirectoriesAndFiles) { DownloadDirectoryOrFile(subFile, directoryPath); } } }
/// <summary> /// 下载一个单一的文件和目录. /// </summary> void DownloadDirectoryOrFile(FTPFileSystem fileSystem, string localPath) { // 下载文件目录. if (!fileSystem.IsDirectory) { DownloadFile(fileSystem, localPath); } // 下载一个目录. else { //目录路径的结构. string directoryPath = localPath + "\\" + fileSystem.Name; if (!Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } //获得子目录和文件. var subDirectoriesAndFiles = this.manager.GetSubDirectoriesAndFiles(fileSystem.Url); // 下载文件夹的文件和子目录. foreach (var subFile in subDirectoriesAndFiles) { DownloadDirectoryOrFile(subFile, directoryPath); } } }
/// <summary> /// Get the sub directories and files of the Url. It will be used in enumerate /// all the folders. /// When run the FTP LIST protocol method to get a detailed listing of the files /// on an FTP server, the server will response many records of information. Each /// record represents a file. /// </summary> public IEnumerable <FTPFileSystem> GetSubDirectoriesAndFiles(Uri url) { FtpWebRequest request = WebRequest.Create(url) as FtpWebRequest; request.Credentials = this.Credentials; request.UseBinary = true; request.Method = WebRequestMethods.Ftp.ListDirectoryDetails; FtpWebResponse response = null; Stream responseStream = null; StreamReader reader = null; try { response = request.GetResponse() as FtpWebResponse; this.OnNewMessageArrived(new NewMessageEventArg { NewMessage = response.StatusDescription }); responseStream = response.GetResponseStream(); // reader = new StreamReader(responseStream); reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default); List <FTPFileSystem> subDirs = new List <FTPFileSystem>(); string subDir = reader.ReadLine(); // Find out the FTP Directory Listing Style from the recordString. FTPDirectoryListingStyle style = FTPDirectoryListingStyle.MSDOS; if (!string.IsNullOrEmpty(subDir)) { style = FTPFileSystem.GetDirectoryListingStyle(subDir); } while (!string.IsNullOrEmpty(subDir)) { subDirs.Add(FTPFileSystem.ParseRecordString(url, subDir, style)); subDir = reader.ReadLine(); } return(subDirs); } finally { if (response != null) { response.Close(); } // Close the StreamReader object and the underlying stream, and release // any system resources associated with the reader. if (reader != null) { reader.Close(); } } }
/// <summary> /// 获得Url的子目录和文件. 对于所有的文件夹他将使用枚举. /// 在一个FTP 服务上,当运行FTP LIST 协议方法来获得一个文件的详细列表时, /// 这个服务将响应一些信息的记录。每一个记录代表一个文件。 /// </summary> public IEnumerable <FTPFileSystem> GetSubDirectoriesAndFiles(Uri url) { FtpWebRequest request = WebRequest.Create(url) as FtpWebRequest; request.Credentials = this.Credentials; request.Method = WebRequestMethods.Ftp.ListDirectoryDetails; FtpWebResponse response = null; Stream responseStream = null; StreamReader reader = null; try { response = request.GetResponse() as FtpWebResponse; this.OnNewMessageArrived(new NewMessageEventArg { NewMessage = response.StatusDescription }); responseStream = response.GetResponseStream(); reader = new StreamReader(responseStream); List <FTPFileSystem> subDirs = new List <FTPFileSystem>(); string subDir = reader.ReadLine(); //在记录的字符串中找到FTP目录列表类型. FTPDirectoryListingStyle style = FTPDirectoryListingStyle.MSDOS; if (!string.IsNullOrEmpty(subDir)) { style = FTPFileSystem.GetDirectoryListingStyle(subDir); } while (!string.IsNullOrEmpty(subDir)) { subDirs.Add(FTPFileSystem.ParseRecordString(url, subDir, style)); subDir = reader.ReadLine(); } return(subDirs); } finally { if (response != null) { response.Close(); } // 关闭StreamReader对象和底层流,并且释放与reader有关的任何资源。 if (reader != null) { reader.Close(); } } }
/// <summary> /// Get an FTPFileSystem from the recordString. /// </summary> public static FTPFileSystem ParseRecordString(Uri baseUrl, string recordString, FTPDirectoryListingStyle type) { FTPFileSystem fileSystem = null; if (type == FTPDirectoryListingStyle.UNIX) { fileSystem = ParseUNIXRecordString(recordString); } else { fileSystem = ParseMSDOSRecordString(recordString); } // Add "/" to the url if it is a directory fileSystem.Url = new Uri(baseUrl, fileSystem.Name + (fileSystem.IsDirectory ? "/" : string.Empty)); return(fileSystem); }
/// <summary> /// 12-13-10 12:41PM <DIR> Folder A /// </summary> /// <param name="recordString"></param> /// <returns></returns> static FTPFileSystem ParseMSDOSRecordString(string recordString) { FTPFileSystem fileSystem = new FTPFileSystem(); fileSystem.OriginalRecordString = recordString.Trim(); fileSystem.DirectoryListingStyle = FTPDirectoryListingStyle.MSDOS; // 这个部分如 "12-13-10", "", "12:41PM", "", "","", "", // "", "", "<DIR>", "", "", "", "", "", "", "", "", "", "Folder", "A". string[] segments = fileSystem.OriginalRecordString.Split(' '); int index = 0; //这个数据部分如 "12-13-10" instead of "12-13-2010" 如果年是 //四位数就不在ISS中查找 string dateSegment = segments[index]; string[] dateSegments = dateSegment.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries); int month = int.Parse(dateSegments[0]); int day = int.Parse(dateSegments[1]); int year = int.Parse(dateSegments[2]); //如果year大于等于50并且小雨100,将意味着这个年时19** if (year >= 50 && year < 100) { year += 1900; } //如果year小于50,它意味着年时20** else if (year < 50) { year += 2000; } //跳过空的部分. while (segments[++index] == string.Empty) { } // 时间部分. string timesegment = segments[index]; fileSystem.ModifiedTime = DateTime.Parse(string.Format("{0}-{1}-{2} {3}", year, month, day, timesegment)); // 跳过空的部分. while (segments[++index] == string.Empty) { } // 这个部分的大小和目录 . //如果这部分是 "<DIR>", 它意味着是一个目录,否则它是一个文件的大小。 string sizeOrDirSegment = segments[index]; fileSystem.IsDirectory = sizeOrDirSegment.Equals("<DIR>", StringComparison.OrdinalIgnoreCase); //如果这个文件流是一个文件,这个大小是大于0的. if (!fileSystem.IsDirectory) { fileSystem.Size = int.Parse(sizeOrDirSegment); } // 掉过空的部分. while (segments[++index] == string.Empty) { } // 在原始字符串中计算文件名索引的部分. int filenameIndex = 0; for (int i = 0; i < index; i++) { // 在原始字符串中的"" 表示' '. if (segments[i] == string.Empty) { filenameIndex += 1; } else { filenameIndex += segments[i].Length + 1; } } //这个名可能包含一些空字符. fileSystem.Name = fileSystem.OriginalRecordString.Substring(filenameIndex).Trim(); return(fileSystem); }
/// <summary> /// 这个recordString是像: /// 目录: drwxrwxrwx 1 owner group 0 Dec 13 11:25 Folder A /// 文件: -rwxrwxrwx 1 owner group 1024 Dec 13 11:25 File B /// 注意: 这个日期设置不能包括年. /// </summary> static FTPFileSystem ParseUNIXRecordString(string recordString) { FTPFileSystem fileSystem = new FTPFileSystem(); fileSystem.OriginalRecordString = recordString.Trim(); fileSystem.DirectoryListingStyle = FTPDirectoryListingStyle.UNIX; // 这个设置如 "drwxrwxrwx", "", "", "1", "owner", "", "", "", // "group", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // "0", "Dec", "13", "11:25", "Folder", "A". string[] segments = fileSystem.OriginalRecordString.Split(' '); int index = 0; //这个权限设置如: "drwxrwxrwx". string permissionsegment = segments[index]; // 如果这个属性第一个字母是 'd', 它意味着是一个目录. fileSystem.IsDirectory = permissionsegment[0] == 'd'; // 跳过空的部分. while (segments[++index] == string.Empty) { } // 跳过部分的目录. // 跳过空的部分. while (segments[++index] == string.Empty) { } // 跳过这组的部分. //跳过空的部分 . while (segments[++index] == string.Empty) { } //跳过组的这部分. //跳过空的部分. while (segments[++index] == string.Empty) { } // 如果这个文件流是一个文件, 它的大小大于0. fileSystem.Size = int.Parse(segments[index]); // 跳过空的部分. while (segments[++index] == string.Empty) { } // 月的部分. string monthsegment = segments[index]; // 跳过空的部分. while (segments[++index] == string.Empty) { } // 日期部分. string daysegment = segments[index]; // 跳过这个空的部分. while (segments[++index] == string.Empty) { } // 时间部分. string timesegment = segments[index]; fileSystem.ModifiedTime = DateTime.Parse(string.Format("{0} {1} {2} ", timesegment, monthsegment, daysegment)); // 跳过空的部分 while (segments[++index] == string.Empty) { } //在原始字符串中计算文件名索引的部分 int filenameIndex = 0; for (int i = 0; i < index; i++) { // 在原始字符串中的"" 表示' '. if (segments[i] == string.Empty) { filenameIndex += 1; } else { filenameIndex += segments[i].Length + 1; } } // 这个名可能包含一些空字符. fileSystem.Name = fileSystem.OriginalRecordString.Substring(filenameIndex).Trim(); return(fileSystem); }
/// <summary> /// 这个recordString是像: /// 目录: drwxrwxrwx 1 owner group 0 Dec 13 11:25 Folder A /// 文件: -rwxrwxrwx 1 owner group 1024 Dec 13 11:25 File B /// 注意: 这个日期设置不能包括年. /// </summary> static FTPFileSystem ParseUNIXRecordString(string recordString) { FTPFileSystem fileSystem = new FTPFileSystem(); fileSystem.OriginalRecordString = recordString.Trim(); fileSystem.DirectoryListingStyle = FTPDirectoryListingStyle.UNIX; // 这个设置如 "drwxrwxrwx", "", "", "1", "owner", "", "", "", // "group", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // "0", "Dec", "13", "11:25", "Folder", "A". string[] segments = fileSystem.OriginalRecordString.Split(' '); int index = 0; //这个权限设置如: "drwxrwxrwx". string permissionsegment = segments[index]; // 如果这个属性第一个字母是 'd', 它意味着是一个目录. fileSystem.IsDirectory = permissionsegment[0] == 'd'; // 跳过空的部分. while (segments[++index] == string.Empty) { } // 跳过部分的目录. // 跳过空的部分. while (segments[++index] == string.Empty) { } // 跳过这组的部分. //跳过空的部分 . while (segments[++index] == string.Empty) { } //跳过组的这部分. //跳过空的部分. while (segments[++index] == string.Empty) { } // 如果这个文件流是一个文件, 它的大小大于0. fileSystem.Size = int.Parse(segments[index]); // 跳过空的部分. while (segments[++index] == string.Empty) { } // 月的部分. string monthsegment = segments[index]; // 跳过空的部分. while (segments[++index] == string.Empty) { } // 日期部分. string daysegment = segments[index]; // 跳过这个空的部分. while (segments[++index] == string.Empty) { } // 时间部分. string timesegment = segments[index]; fileSystem.ModifiedTime = DateTime.Parse(string.Format("{0} {1} {2} ", timesegment, monthsegment, daysegment)); // 跳过空的部分 while (segments[++index] == string.Empty) { } //在原始字符串中计算文件名索引的部分 int filenameIndex = 0; for (int i = 0; i < index; i++) { // 在原始字符串中的"" 表示' '. if (segments[i] == string.Empty) { filenameIndex += 1; } else { filenameIndex += segments[i].Length + 1; } } // 这个名可能包含一些空字符. fileSystem.Name = fileSystem.OriginalRecordString.Substring(filenameIndex).Trim(); return fileSystem; }
/// <summary> /// 12-13-10 12:41PM <DIR> Folder A /// </summary> /// <param name="recordString"></param> /// <returns></returns> static FTPFileSystem ParseMSDOSRecordString(string recordString) { FTPFileSystem fileSystem = new FTPFileSystem(); fileSystem.OriginalRecordString = recordString.Trim(); fileSystem.DirectoryListingStyle = FTPDirectoryListingStyle.MSDOS; // 这个部分如 "12-13-10", "", "12:41PM", "", "","", "", // "", "", "<DIR>", "", "", "", "", "", "", "", "", "", "Folder", "A". string[] segments = fileSystem.OriginalRecordString.Split(' '); int index = 0; //这个数据部分如 "12-13-10" instead of "12-13-2010" 如果年是 //四位数就不在ISS中查找 string dateSegment = segments[index]; string[] dateSegments = dateSegment.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries); int month = int.Parse(dateSegments[0]); int day = int.Parse(dateSegments[1]); int year = int.Parse(dateSegments[2]); //如果year大于等于50并且小雨100,将意味着这个年时19** if (year >= 50 && year < 100) { year += 1900; } //如果year小于50,它意味着年时20** else if (year < 50) { year += 2000; } //跳过空的部分. while (segments[++index] == string.Empty) { } // 时间部分. string timesegment = segments[index]; fileSystem.ModifiedTime = DateTime.Parse(string.Format("{0}-{1}-{2} {3}", year, month, day, timesegment)); // 跳过空的部分. while (segments[++index] == string.Empty) { } // 这个部分的大小和目录 . //如果这部分是 "<DIR>", 它意味着是一个目录,否则它是一个文件的大小。 string sizeOrDirSegment = segments[index]; fileSystem.IsDirectory = sizeOrDirSegment.Equals("<DIR>", StringComparison.OrdinalIgnoreCase); //如果这个文件流是一个文件,这个大小是大于0的. if (!fileSystem.IsDirectory) { fileSystem.Size = int.Parse(sizeOrDirSegment); } // 掉过空的部分. while (segments[++index] == string.Empty) { } // 在原始字符串中计算文件名索引的部分. int filenameIndex = 0; for (int i = 0; i < index; i++) { // 在原始字符串中的"" 表示' '. if (segments[i] == string.Empty) { filenameIndex += 1; } else { filenameIndex += segments[i].Length + 1; } } //这个名可能包含一些空字符. fileSystem.Name = fileSystem.OriginalRecordString.Substring(filenameIndex).Trim(); return fileSystem; }
/// <summary> /// 12-13-10 12:41PM <DIR> Folder A /// </summary> /// <param name="recordString"></param> /// <returns></returns> static FTPFileSystem ParseMSDOSRecordString(string recordString) { FTPFileSystem fileSystem = new FTPFileSystem(); fileSystem.OriginalRecordString = recordString.Trim(); fileSystem.DirectoryListingStyle = FTPDirectoryListingStyle.MSDOS; // The segments is like "12-13-10", "", "12:41PM", "", "","", "", // "", "", "<DIR>", "", "", "", "", "", "", "", "", "", "Folder", "A". string[] segments = fileSystem.OriginalRecordString.Split(' '); int index = 0; // The date segment is like "12-13-10" instead of "12-13-2010" if Four-digit years // is not checked in IIS. string dateSegment = segments[index]; string[] dateSegments = dateSegment.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries); int month = int.Parse(dateSegments[0]); int day = int.Parse(dateSegments[1]); int year = int.Parse(dateSegments[2]); // If year >=50 and year <100, then it means the year 19** if (year >= 50 && year < 100) { year += 1900; } // If year <50, then it means the year 20** else if (year < 50) { year += 2000; } // Skip the empty segments. while (segments[++index] == string.Empty) { } // The time segment. string timesegment = segments[index]; fileSystem.ModifiedTime = DateTime.Parse(string.Format("{0}-{1}-{2} {3}", year, month, day, timesegment)); // Skip the empty segments. while (segments[++index] == string.Empty) { } // The size or directory segment. // If this segment is "<DIR>", then it means a directory, else it means the // file size. string sizeOrDirSegment = segments[index]; fileSystem.IsDirectory = sizeOrDirSegment.Equals("<DIR>", StringComparison.OrdinalIgnoreCase); // If this fileSystem is a file, then the size is larger than 0. if (!fileSystem.IsDirectory) { fileSystem.Size = int.Parse(sizeOrDirSegment); } // Skip the empty segments. while (segments[++index] == string.Empty) { } // Calculate the index of the file name part in the original string. int filenameIndex = 0; for (int i = 0; i < index; i++) { // "" represents ' ' in the original string. if (segments[i] == string.Empty) { filenameIndex += 1; } else { filenameIndex += segments[i].Length + 1; } } // The file name may include many segments because the name can contain ' '. fileSystem.Name = fileSystem.OriginalRecordString.Substring(filenameIndex).Trim(); return(fileSystem); }
/// <summary> /// The recordString is like /// Directory: drwxrwxrwx 1 owner group 0 Dec 13 11:25 Folder A /// File: -rwxrwxrwx 1 owner group 1024 Dec 13 11:25 File B /// NOTE: The date segment does not contains year. /// </summary> static FTPFileSystem ParseUNIXRecordString(string recordString) { FTPFileSystem fileSystem = new FTPFileSystem(); fileSystem.OriginalRecordString = recordString.Trim(); fileSystem.DirectoryListingStyle = FTPDirectoryListingStyle.UNIX; // The segments is like "drwxrwxrwx", "", "", "1", "owner", "", "", "", // "group", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // "0", "Dec", "13", "11:25", "Folder", "A". string[] segments = fileSystem.OriginalRecordString.Split(' '); int index = 0; // The permission segment is like "drwxrwxrwx". string permissionsegment = segments[index]; // If the property start with 'd', then it means a directory. fileSystem.IsDirectory = permissionsegment[0] == 'd'; // Skip the empty segments. while (segments[++index] == string.Empty) { } // Skip the directories segment. // Skip the empty segments. while (segments[++index] == string.Empty) { } // Skip the owner segment. // Skip the empty segments. while (segments[++index] == string.Empty) { } // Skip the group segment. // Skip the empty segments. while (segments[++index] == string.Empty) { } // If this fileSystem is a file, then the size is larger than 0. fileSystem.Size = int.Parse(segments[index]); // Skip the empty segments. while (segments[++index] == string.Empty) { } // The month segment. string monthsegment = segments[index]; // Skip the empty segments. while (segments[++index] == string.Empty) { } // The day segment. string daysegment = segments[index]; // Skip the empty segments. while (segments[++index] == string.Empty) { } // The time segment. string timesegment = segments[index]; fileSystem.ModifiedTime = DateTime.Parse(string.Format("{0} {1} {2} ", timesegment, monthsegment, daysegment)); // Skip the empty segments. while (segments[++index] == string.Empty) { } // Calculate the index of the file name part in the original string. int filenameIndex = 0; for (int i = 0; i < index; i++) { // "" represents ' ' in the original string. if (segments[i] == string.Empty) { filenameIndex += 1; } else { filenameIndex += segments[i].Length + 1; } } // The file name may include many segments because the name can contain ' '. fileSystem.Name = fileSystem.OriginalRecordString.Substring(filenameIndex).Trim(); return(fileSystem); }
/// <summary> /// 下载一个单一的文件目录. /// </summary> void DownloadFile(FTPFileSystem file, string localPath) { if (file.IsDirectory) { throw new ArgumentException( "The FTPFileSystem to download is a directory in fact"); } string destPath = localPath + "\\" + file.Name; //创建一个要下载的文件的请求. FtpWebRequest request = WebRequest.Create(file.Url) as FtpWebRequest; request.Credentials = this.manager.Credentials; // 下载文件. request.Method = WebRequestMethods.Ftp.DownloadFile; FtpWebResponse response = null; Stream responseStream = null; MemoryStream downloadCache = null; try { //检索来自服务器的响应,并得到响应流. response = request.GetResponse() as FtpWebResponse; this.manager.OnNewMessageArrived(new NewMessageEventArg { NewMessage = response.StatusDescription }); responseStream = response.GetResponseStream(); //内存中的缓存数据. downloadCache = new MemoryStream(FTPDownloadClient.MaxCacheSize); byte[] downloadBuffer = new byte[FTPDownloadClient.BufferSize]; int bytesSize = 0; int cachedSize = 0; // 下载这个文件直到下载完成. while (true) { //从流中读取数据的缓冲区。 bytesSize = responseStream.Read(downloadBuffer, 0, downloadBuffer.Length); //如果这个缓存区是空的,或者下载完成,把在缓存中的数据写到本地文件中。 if (bytesSize == 0 || MaxCacheSize < cachedSize + bytesSize) { try { // 把在缓存中的数据写到本地文件中. WriteCacheToFile(downloadCache, destPath, cachedSize); //如果被暂停下载将停止正在下载的文件,取消或者完成. if (bytesSize == 0) { break; } // 重置缓存. downloadCache.Seek(0, SeekOrigin.Begin); cachedSize = 0; } catch (Exception ex) { string msg = string.Format( "There is an error while downloading {0}. " + " See InnerException for detailed error. ", file.Url); ApplicationException errorException = new ApplicationException(msg, ex); //这个错误给了DownloadCompleted事件 ErrorEventArgs e = new ErrorEventArgs { ErrorException = errorException }; this.manager.OnErrorOccurred(e); return; } } //把缓冲区的数据写到内存中的缓存。 downloadCache.Write(downloadBuffer, 0, bytesSize); cachedSize += bytesSize; } var fileDownloadCompletedEventArgs = new FileDownloadCompletedEventArgs { LocalFile = new FileInfo(destPath), ServerPath = file.Url }; this.OnFileDownloadCompleted(fileDownloadCompletedEventArgs); } finally { if (response != null) { response.Close(); } if (responseStream != null) { responseStream.Close(); } if (downloadCache != null) { downloadCache.Close(); } } }
/// <summary> /// Download a single file directly. /// </summary> void DownloadFile(FTPFileSystem file, string localPath) { if (file.IsDirectory) { throw new ArgumentException( "The FTPFileSystem to download is a directory in fact"); } string destPath = localPath + "\\" + file.Name; // Create a request to the file to be downloaded. FtpWebRequest request = WebRequest.Create(file.Url) as FtpWebRequest; request.Credentials = this.manager.Credentials; // Download file. request.Method = WebRequestMethods.Ftp.DownloadFile; FtpWebResponse response = null; Stream responseStream = null; MemoryStream downloadCache = null; try { // Retrieve the response from the server and get the response stream. response = request.GetResponse() as FtpWebResponse; this.manager.OnNewMessageArrived(new NewMessageEventArg { NewMessage = response.StatusDescription }); responseStream = response.GetResponseStream(); // Cache data in memory. downloadCache = new MemoryStream(FTPDownloadClient.MaxCacheSize); byte[] downloadBuffer = new byte[FTPDownloadClient.BufferSize]; int bytesSize = 0; int cachedSize = 0; // Download the file until the download is completed. while (true) { // Read a buffer of data from the stream. bytesSize = responseStream.Read(downloadBuffer, 0, downloadBuffer.Length); // If the cache is full, or the download is completed, write // the data in cache to local file. if (bytesSize == 0 || MaxCacheSize < cachedSize + bytesSize) { try { // Write the data in cache to local file. WriteCacheToFile(downloadCache, destPath, cachedSize); // Stop downloading the file if the download is paused, // canceled or completed. if (bytesSize == 0) { break; } // Reset cache. downloadCache.Seek(0, SeekOrigin.Begin); cachedSize = 0; } catch (Exception ex) { string msg = string.Format( "There is an error while downloading {0}. " + " See InnerException for detailed error. ", file.Url); ApplicationException errorException = new ApplicationException(msg, ex); // Fire the DownloadCompleted event with the error. ErrorEventArgs e = new ErrorEventArgs { ErrorException = errorException }; this.manager.OnErrorOccurred(e); return; } } // Write the data from the buffer to the cache in memory. downloadCache.Write(downloadBuffer, 0, bytesSize); cachedSize += bytesSize; } var fileDownloadCompletedEventArgs = new FileDownloadCompletedEventArgs { LocalFile = new FileInfo(destPath), ServerPath = file.Url }; this.OnFileDownloadCompleted(fileDownloadCompletedEventArgs); } finally { if (response != null) { response.Close(); } if (responseStream != null) { responseStream.Close(); } if (downloadCache != null) { downloadCache.Close(); } } }