工具开发系列之:文件下载+断点续传
2013-12-12 18:01 by Turbo Zhang, 325 阅读, 1 评论, 收藏, 编辑
日常开发中总会遇到大量琐碎文件的Copy处理的问题,而如果文件较大的情况下,可能会遇到断电,远程Server崩溃等问题,于是断点续传问题就会提到议事上来。
在这里分享一个自己用的DownLoad Tool 虽然细节有待商讨,暂起抛砖引玉之意:
- 新建控制台程序作为tool主程:
-
static void Main(string[] args) { Console.WriteLine("{0:HH:mm:ss} Download tool start......",DateTime.Now); DownLoadFunction.StartDownload(); Console.WriteLine("{0:HH:mm:ss} Download finished! Press <Enter> to exit.",DateTime.Now); Console.ReadLine(); }
-
- 相关Code:
DownLoadFunction 作为下载主要类,实现下载功能,后续提供的FTP,HTTP等下载方式以工厂方式提供:
public static Boolean StartDownload() { String srcPath = System.Configuration.ConfigurationManager.AppSettings["SourcePath"]; String aimPath = System.Configuration.ConfigurationManager.AppSettings["TargetPath"]; try { IOHelper.WriteToXml(srcPath,aimPath); LoadFile(srcPath, aimPath); IOHelper.XmlDelete(); return true; } catch (Exception ex) { Console.WriteLine("{0:HH:mm:ss} error:" + ex,DateTime.Now); } return false; }
下面的方法为核心方法,首先建立远程下载目录文件,下载工程依次修改此文件相关条目状态。
下载完成,相关条目状态设置为100%;
文件夹下文件以递归方式实现(此处为出现性能问题的地区);
如果下载过程中由于异常程序终止,下次下载时,程序发现上次记录过此目录,进行下载条目检查,状态未成100%的,则由此次进行下载,以实现断点下载。
(如果想更加精细的实现“断点”,需要操作到file本身的属性,md5等各种校验)
Code如下:
#region private method private static void LoadFile(String srcPath, String aimPath) { Console.WriteLine("[Enter Path]: {0}",srcPath); try { if (aimPath[aimPath.Length - 1] != System.IO.Path.DirectorySeparatorChar) { aimPath += System.IO.Path.DirectorySeparatorChar; } if (!System.IO.Directory.Exists(aimPath)) { System.IO.Directory.CreateDirectory(aimPath); } String[] fileList = System.IO.Directory.GetFileSystemEntries(srcPath); foreach (String file in fileList) { if (System.IO.Directory.Exists(file)) { Console.WriteLine("[Enter Path]: {0}",file); LoadFile(file, aimPath + System.IO.Path.GetFileName(file)); } else { if (IOHelper.CheckDownloadState(file) != DownloadState.Finished) { Console.WriteLine("[Download file]: {0}", file); System.IO.File.Copy(file, aimPath + System.IO.Path.GetFileName(file), true); IOHelper.UpdateDownlPer(file); } } } } catch (Exception e) { Console.WriteLine("{0:HH:mm:ss} error:" + e, DateTime.Now); } } #endregion
对于下载条目文件的操作:
public class IOHelper { #region Create directory public static void DirectoryCreate(String directoryName) { String createPath = Path.GetDirectoryName(directoryName); try { if (!Directory.Exists(createPath)) { Directory.CreateDirectory(createPath); } Console.WriteLine("{0:HH:mm:ss} directory {0} create successful!",directoryName); } catch (Exception ex) { Console.WriteLine("{0:HH:mm:ss} Create directory error! message:"+ex); } } #endregion #region Config operate static StringBuilder sbXml = new StringBuilder(); static readonly String xmlTargetPath = System.Configuration.ConfigurationManager.AppSettings["xmlPath"]; public static void WriteToXml(String srcPath, String aimPath) { if (File.Exists(xmlTargetPath)) return; try { if (aimPath[aimPath.Length - 1] != System.IO.Path.DirectorySeparatorChar) { aimPath += System.IO.Path.DirectorySeparatorChar; } if (!System.IO.Directory.Exists(aimPath)) { System.IO.Directory.CreateDirectory(aimPath); } String[] fileList = System.IO.Directory.GetFileSystemEntries(srcPath); foreach (String file in fileList) { if (System.IO.Directory.Exists(file)) { WriteToXml(file, aimPath + System.IO.Path.GetFileName(file)); } else { sbXml.AppendLine(file+"->0%"); } } File.WriteAllText(xmlTargetPath,sbXml.ToString(),Encoding.UTF8); } catch (Exception e) { Console.WriteLine("{0:HH:mm:ss} write to xml error:" + e, DateTime.Now); } } public static void UpdateDownlPer(String line) { String[] lines = File.ReadAllLines(xmlTargetPath); for (int i = 0; i < lines.Length; i++) { if (line == lines[i].Substring(0, lines[i].LastIndexOf("->"))) { lines[i] = lines[i].Substring(0,lines[i].LastIndexOf("->")+2)+"100%"; break; } } File.WriteAllLines(xmlTargetPath,lines,Encoding.UTF8); } public static DownloadState CheckDownloadState(String line) { DownloadState state=DownloadState.Start; String[] lines = File.ReadAllLines(xmlTargetPath); for (int i = 0; i < lines.Length; i++) { if (line == lines[i].Substring(0, lines[i].LastIndexOf("->"))) { if (lines[i].Substring(lines[i].LastIndexOf("->") + 2) == "100%") state = DownloadState.Finished; else state = DownloadState.Start; break; } } return state; } public static void XmlDelete() { File.Delete(xmlTargetPath); } #endregion }
public enum TaskState { Create, Processing, Error, Finished }
XML:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <appSettings> <add key="xmlPath" value="d:\dbCopy\configXml.txt"/> <add key="SourcePath" value="D:\TestFile\"/> <add key="TargetPath" value="D:\dbCopy\"/> </appSettings> </configuration>
3.执行结果:
下载条目列表:
程序结果: