zoukankan      html  css  js  c++  java
  • 文件下载+断点续传

    工具开发系列之:文件下载+断点续传

    2013-12-12 18:01 by Turbo Zhang, 325 阅读, 1 评论, 收藏编辑

    日常开发中总会遇到大量琐碎文件的Copy处理的问题,而如果文件较大的情况下,可能会遇到断电,远程Server崩溃等问题,于是断点续传问题就会提到议事上来。

    在这里分享一个自己用的DownLoad Tool 虽然细节有待商讨,暂起抛砖引玉之意:

    1. 新建控制台程序作为tool主程:
      1. 复制代码
        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();
                }
        复制代码


         

    2. 相关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:dbCopyconfigXml.txt"/>
        <add key="SourcePath" value="D:TestFile"/>
        <add key="TargetPath" value="D:dbCopy"/>
      </appSettings>
    </configuration>
    复制代码

    3.执行结果:

    下载条目列表:

     程序结果:

  • 相关阅读:
    一致性哈希算法
    Discourse 的标签(Tag)只能是小写的原因
    JIRA 链接 bitbucket 提示错误 Invalid OAuth credentials
    JIRA 如何连接到云平台的 bitbucket
    Apache Druid 能够支持即席查询
    如何在 Discourse 中配置使用 GitHub 登录和创建用户
    Apache Druid 是什么
    Xshell 如何导入 PuTTYgen 生成的 key
    windows下配置Nginx支持php
    laravel连接数据库提示mysql_connect() :Connection refused...
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3472199.html
Copyright © 2011-2022 走看看