• 阿里云客户端的实现(支持文件分块,断点续传,进度,速度,倒计时显示)


    一,以实际案例引入阿里云的运用

    好多人都在玩概念,玩什么概念,比如工业4.0

    什么叫工业4.0,简单一点理解就是 “互联网” + “制造”(互联网+)。再通俗一些的理解就是“互联网”做电商销售,“制造”就是传统生产。

    最终做到有了订单才生产,真正做到了按需生产,解决了企业物料损耗,库存堆积等问题。

    比如:以印刷厂为案例来说工业4.0,一个印刷厂,客户下单才印刷,不能先印刷一堆东西堆在库存里吧!

    先可以看一个流程示意图:

    1,客户通过销售平台下单(印刷数量,规格,付款,以及上传需要印刷的文件,与普通电商销售平台的区别体现在上传文件这儿)

    2,通过一个服务(ESB),把客户的订单信息,文件数据流转到印刷厂的生产系统。

    今天我重点要说的就是ESB服务,怎样高效稳定的把文件从销售平台转到生产系统。

    需求:

    1,因为订单量大,每天有2至3T的文件从销售平台流向生产系统。

    2,这些文件至少要保存一个月左右,有可能返工印刷(算下来企业最小极限要有100个T的存储服务器)。

    经过多方面的考虑,建议选择阿里云的存储。

    二,阿里云存储OSS的开发

    1,支持目录结构的文件,普通文件的传输。

    2,销售平台端上传文件到阿里云服务器,支持多线程的(分块上传,分块校验,断点续传,重试,文件MD5值检验,进度,速度,需要用时的显示)

    3,ESB服务从阿里云服务器下载文件,支持多线程的(分块下载,分块校验,断点续传,重试,文件MD5值检验,进度,速度,需要用时的显示)

    4,把下载的文件经过一系统的预检,处理,最终拷贝到生产系统。

    5,反馈文件处理结果到销售平台,生产系统。

    这几个需求促使我们有必要开发一个个性化的阿里云客户端,这个客户端已经满足了我上面说的的需求。

     三,具体开发介绍

     3.1程序目录结构的介绍

     

    先上图,再来解释。

    不管会不会写程序的,只要是懂点IT的,聊到程序时,都会聊到点架构。落伍一些的就聊“三层架构”,牛批一些的就聊“分布式架构”,在博客园里都能找到上十种的架构。

    在这儿,我就不画架构图了,就以目录来说我的程序架构。

    显而易见:

    这个程序最底层的架构:服务端  + 客户端。

    服务端:数据库的持久化操作,和一些公用接口,比如获取服务器时间服务。

    客户端:UI的数据呈现,下载,文件处理等的业务逻辑。

    其中客户端又包含了一个UI框架:

    这个框架是MVVM模式,相当于B/S结构中的MVC。

    这个UI框架:

    1,实现了XAML与C#代码的分离

    2,实现在IOC的控制反转的模式

    3,利用观察者模板实现了模块与模块之间的解耦

    3.2关键核心的架构代码:

    代码片段1:

    因为整个程序,各个程序之间互相不添加引用,只要在生成项目的时候用这样的命令把dll文件拷贝到UI框架目录下即可

    xcopy $(TargetPath) $(SolutionDir)FileTransfer.ClientinDebug /y
    xcopy $(TargetPath) $(SolutionDir)FileTransfer.ClientinRelease /y

    具休操作如图所示:

     代码片段2:

    因为UI启动程序不添加各dll的引用,目的是使每个功能模板之间的解耦合,所以在启动程序时,需要添加一段引导代码:

        public class AppBootstrapper : BootstrapperBase
        {
            private CompositionContainer container;
    
            public AppBootstrapper()
            {
                Initialize();
            }
    
            protected override void BuildUp(object instance)
            {
                this.container.SatisfyImportsOnce(instance);
            }
    
            /// <summary>
            ///     By default, we are configured to use MEF
            /// </summary>
            protected override void Configure()
            {
                foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
                {
                    AssemblySource.Instance.Add(Assembly.LoadFile(file));
                }
    
                var catalog =
                    new AggregateCatalog(
                        AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());
    
                this.container = new CompositionContainer(catalog);
    
                var batch = new CompositionBatch();
    
                batch.AddExportedValue<IWindowManager>(new WindowManager());
                batch.AddExportedValue<IEventAggregator>(new EventAggregator());
                batch.AddExportedValue(this.container);
                batch.AddExportedValue(catalog);
    
                this.container.Compose(batch);
            }
    
            protected override IEnumerable<object> GetAllInstances(Type serviceType)
            {
                return this.container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
            }
    
            protected override object GetInstance(Type serviceType, string key)
            {
                var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
                var exports = this.container.GetExportedValues<object>(contract);
    
                if (exports.Any())
                {
                    return exports.First();
                }
    
                throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
            }
    
            protected override void OnStartup(object sender, StartupEventArgs e)
            {
                //var startupTasks =
                //    GetAllInstances(typeof(StartupTask))
                //    .Cast<ExportedDelegate>()
                //    .Select(exportedDelegate => (StartupTask)exportedDelegate.CreateDelegate(typeof(StartupTask)));
    
                //startupTasks.Apply(s => s());
                DisplayRootViewFor<FileTransfer.Interface.IShell>();
                //base.OnStartup(sender, e);
            }
        }
    View Code

    这个引导代码有一个很关键的地方,我把它提炼出来:

        foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
        {
            AssemblySource.Instance.Add(Assembly.LoadFile(file));
        }

    就是要把需要的dll,通过一定规则的匹配模式把dll放入到程序的容器中。通过以下的代码来获取实例:

        object obj = IoC.Get<IRetrievePwd>();
        IoC.Get<IWindowManager>().ShowDialog(obj);

     代码片段3:

    观察者模式的实现:

    观察者模式,首先,我们肯定要明白有两个对象,一个是发布信息,一个是接收信息,同时还需要一个契约。如下代码:

        PublishTaskViewModel ptvm = (PublishTaskViewModel)IoC.Get<IPublishTask>();
        ptvm.TaskViewData = taskData;
        ptvm.OperateType = OperateTypeEnum.Edit;
        _eventAggregator.PublishOnUIThread(new ShowMainContentEvent { ContentModel = ptvm });

    其中:
    IPublishTask  就是我定义的观察者模式契约。

    PublishOnUIThread  就是我发出一条消息,发出消息的模式有很多种,如下图:

    订阅对象要实现:

        this._eventAggregator.Subscribe(this);

    再用这样的方法接收信息:

        public void Handle(ShowMainContentEvent message)
        {
    
        }

     四,结语

    一言难尽,还有很多很多要写的地方。这个给公司开发的代码,又不能共享,只能多分享。

    如果大家想学习我这套开发框架构,我也有类似的开源程序,麻烦翻一翻我的博客,有一篇程序写了一个软件,就是用的这个架构。并且UI做的比这个更靓哦!

    如果大家感觉赞,就动动手指帮我点一下推荐吧!谢谢您能看到这儿。

  • 相关阅读:
    python文件处理-读、写
    Python三元运算和lambda表达式
    可变、不可变数据类型和hash
    Python常见字符编码间的转换
    Python常用字符编码
    spring cloud 使用spring cloud bus自动刷新配置
    spring cloud config--client
    spring cloud Config--server
    git 小乌龟安装教程
    spring cloud Eureka常见问题总结
  • 原文地址:https://www.cnblogs.com/xcj26/p/5887384.html
Copyright © 2020-2023  润新知