首先声明,本人文笔不好,大家见笑,欢迎高手吐槽.

做c/s开发肯定会遇到的就是自动升级功能,而这实现方式是非常多. 本文使用 webservice的方式来提供升级服务

  


首先准备服务

为了方便我们专门用一个文件夹来存放需要更新的应用程序

因为觉得通过新版本来更新很麻烦,所以验证文件是否需要更新用md5来判断

WebService:

 public string GetVer()
{
DirectoryInfo dir = new DirectoryInfo(Server.MapPath("update"));
var list = new List<object>();
var url = string.Format("http://{0}:{1}/update/", HttpContext.Current.Request.Url.Host,
HttpContext.Current.Request.Url.Port); DirectoryInfoHelper.SetDirectoryInfo(dir, list, url, "");
JavaScriptSerializer json = new JavaScriptSerializer();
return json.Serialize(list);
}

相关方法:

public static void SetDirectoryInfo(DirectoryInfo dir, List<object> list, string url, string dirName)
{
foreach (var file in dir.GetFiles())
{
FileStream fs = File.OpenRead(file.FullName);
list.Add(new { file.Name, Md5 = Security.GetMd5(fs), LocalHost = url, Directory = dirName });
fs.Close();
}
foreach (var dirInfo in dir.GetDirectories())
{
SetDirectoryInfo(dirInfo, list, url, string.Format("{0}{1}/", dirName, dirInfo.Name));
}
}

说明:1.不创建模型,而服务端只需要提供数据,所以采用匿名对象

2.GetVer服务返回信息中 包含 文件名,md5值,域名地址,该文件上级目录


C/S:

先看界面

现在就跟着提示消息走吧.

1.获取服务文件特征

调用webservice获取文件信息

private List<VerMd5Date> GetServerData()
{
AutoUpdate.Update update = new AutoUpdate.Update();
var json = update.GetVer();
var list = AppCode.JsonHelper.JsonDeserialize<VerMd5Dates>(json);
return list;
}

客户端需要反序列化json 所以建了一个对应model

public class VerMd5Date
{
public string Name { get; set; }
public string Md5 { get; set; }
public string LocalHost { get; set; }
public string Directory { get; set; }
}
class VerMd5Dates : List<VerMd5Date>
{
}

反序列化:

 /// <summary>
/// 反序列化json
/// </summary>
/// <typeparam name="T">对象</typeparam>
/// <param name="jsonString">json字符串</param>
public static T JsonDeserialize<T>(string jsonString)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
T obj = (T)ser.ReadObject(ms);
return obj;
}

2.获取本地文件特征

private List<VerMd5Date> GetLocalData(List<string> serverNames)
{
DirectoryInfo dir = new DirectoryInfo(Application.StartupPath);
var list = new List<VerMd5Date>();
DirectoryInfoHelper.GetDirectoryInfo(dir, list,"",serverNames);
return list;
}

相关方法:

public static void GetDirectoryInfo(DirectoryInfo dir, List<VerMd5Date> list, string dirName, List<string> serverNames)
{
foreach (var file in dir.GetFiles().Where(m=>serverNames.Contains(dirName+m.Name)))
{
using (FileStream fs = File.OpenRead(file.FullName))
{
list.Add(new VerMd5Date
{
Name = file.Name,
Directory = dirName,
Md5 = Security.GetMd5(fs)
});
}
}
foreach (var dirInfo in dir.GetDirectories())
{
GetDirectoryInfo(dirInfo, list, string.Format("{0}{1}/", dirName, dirInfo.Name), serverNames);
}
}

说明:serverNames 是服务器文件名集合,主要用来排除本地文件夹中非本程序文件

3.对比文件差异

private List<VerMd5Date> EqualsList(List<VerMd5Date> list, List<VerMd5Date> localList)
{
var getList = new List<VerMd5Date>();
foreach (var ver in list)
{
var file = localList.FirstOrDefault(m => m.Name == ver.Name && m.Directory == ver.Directory);
if (file == null)
{
getList.Add(ver);
}
else
{
if (file.Md5 != ver.Md5 && file.Directory == ver.Directory)
{
getList.Add(ver);
}
}
}
return getList;
}

4.下面就开始下载吧

foreach (var file in _getList)
{
SetItem(string.Format("正在下载 {0}{1}", file.Directory, file.Name));
DownloadFile(file.LocalHost, file.Directory, file.Name, progressBar1);
}
DownloadFile:
public void DownloadFile(string localHost, string dirName, string filename, ProgressBar prog)
{
try
{
WebRequest rq = WebRequest.Create(string.Format("{0}{1}{2}", localHost, dirName, filename));
WebResponse rp = rq.GetResponse(); if (prog != null)
{
SetProg((int) rp.ContentLength, );
}
string path = string.Format("{0}/{1}", Application.StartupPath, dirName);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
Stream newFile = File.Create(string.Format("{0}{1}", dirName, filename));
Stream serviceFile = rp.GetResponseStream();
if (serviceFile == null)
return; long totalDownloadedByte = ;
byte[] by = new byte[];
int osize = serviceFile.Read(by, , by.Length);
while (osize > )
{
if (!cbCpu.Checked)
Thread.Sleep(); newFile.Write(by, , osize);
osize = serviceFile.Read(by, , by.Length);
if (prog == null)
continue; totalDownloadedByte = osize + totalDownloadedByte;
SetProg((int) totalDownloadedByte, );
}
newFile.Close();
serviceFile.Close();
SetItem("下载完成");
}
catch(Exception e)
{
SetItem(string.Format("---程序异常:{0}", e.Message));
}
}

下载方式有很多,这里已经有了文件的下载地址,下载代码大家就尽情发挥.有什么好的方式也告诉我一下,非常感谢

运行截图

基本上就完了.欢迎高手吐槽.

很多朋友说dll文件无法下载,本人测试时没问题的.

还有其他特殊文件如cs,config.这里提供2中解决方案

1.先压缩,下载完后解压

2.改后缀,什么后缀随意,只要排除特殊不能下载的后缀

源码地址:http://download.csdn.net/detail/fenglove123/6031397

c/s 自动升级(WebService)的更多相关文章

  1. 分享一个客户端程序(winform)自动升级程序,思路+说明+源码

    做winform的程序,不管用没用过自动更新,至少都想过自动更新是怎么实现的. 我这里共享一个自动更新的一套版本,给还没下手开始写的人一些帮助,也希望有大神来到,给指点优化意见. 本初我是通过sock ...

  2. 在WinForm中使用Web Services 来实现 软件自动升级( Auto Update ) (C#)

    winform程序相对web程序而言,功能更强大,编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,面对这个实际问题,在最近的一个小项目中,本人设计了一个通过软件实现自动升级技术方案,弥补了 ...

  3. c# winform 自动升级

    winform自动升级程序示例源码下载  客户端思路: 1.新建一个配置文件Update.ini,用来存放软件的客户端版本: [update] version=2011-09-09 15:26 2.新 ...

  4. 在WinForm中使用Web Services 来实现 软件 自动升级( Auto Update ) (C#)

    winform程序相对web程序而言,功能更强大,编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,面对这个实际问题,在最近的一个小项目中,本人设计了一个通过软件实现自动升级技术方案,弥补了 ...

  5. Excel催化剂开源第6波-Clickonce部署之自动升级瘦身之术

    Clickonce无痛自动更新是我最喜欢使用VSTO开发并Clickonce部署的特性之一,但这个自动更新,通常会更新整个程序文件,包含所有的引用dll和一些资源文件等. 一般来说,我们更新的都是主程 ...

  6. Ionic实战 自动升级APP(Android版)

    Ionic 框架介绍 Ionic是一个基于Angularjs.可以使用HTML5构建混合移动应用的用户界面框架,它自称为是"本地与HTML5的结合".该框架提供了很多基本的移动用户 ...

  7. 黄聪:C#Winform程序如何发布并自动升级(图解)

    有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...

  8. NetworkComms 文件上传下载和客户端自动升级(非开源)

    演示程序下载地址:http://pan.baidu.com/s/1geVfmcr 淘宝地址:https://shop183793329.taobao.com 联系QQ号:3201175853 许可:购 ...

  9. 【转】C#Winform程序如何发布并自动升级(图解)

    有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...

随机推荐

  1. 烂泥:ubuntu下配置msmtp+mutt发送邮件

    本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb. 本文主要介绍如何在Linux下使用msmtp+mutt发送邮件,当然Linux下发送邮 ...

  2. Linux IPC socket编程基础

    头文件 #include<unistd.h> #include <sys/types.h> #include <sys/socket.h> #include< ...

  3. 使用elasticsearch的关键技术点

    前言 最近有一个项目用到了搜索引擎,这里记录下使用过程中遇到的一些问题和解决方案. 0.准备工作 1)安装elasticsearch 2)安装Marvel 3)安装head tips:在es的配置文件 ...

  4. LNMP源码安装

    1. mysql安装 # Preconfiguration setup shell > groupadd mysql shell > useradd -r -g mysql -s /bin ...

  5. java报表工具finereport常用函数的用法总结(数组函数)

    ADD2ARRAY ADDARRAY(array,insertArray, start):在数组第start个位置插入insertArray中的所有元素,再返回该数组. 示例: ADDARRAY([3 ...

  6. 【温故而知新-Javascript】使用canvas元素(第一部分)

    1. 开始使用 canvas 元素 canvas 元素非常简单,这是指它所有的功能都体现在一个JavaScript对象上,因此该元素本身只有两个属性:width 和 height. canvas 元素 ...

  7. 设计模式——抽象工厂模式及java实现

    设计模式--抽象工厂模式及java实现 设计模式在大型软件工程中很重要,软件工程中采用了优秀的设计模式有利于代码维护,方便日后更改和添加功能. 设计模式有很多,而且也随着时间在不断增多,其中最著名的是 ...

  8. AC日记——合法C标识符 openjudge 1.7 06

    06:合法 C 标识符 总时间限制:  1000ms 内存限制:   65536kB 描述 给定一个不包含空白符的字符串,请判断是否是C语言合法的标识符号(注:题目保证这些字符串一定不是C语言的保留字 ...

  9. 嵌入式Linux驱动学习之路(九)Linux系统调用、驱动程序框架

    应用程序通过open  read  write close 等函数来操作计算机硬件.类似是一个接口. 当应用程序调用这些接口程序时,计算机是如何进入内核的呢?这是经过了系统调用. 实际上当调用接口函数 ...

  10. [No000023]为何没有更多人从事程序员的工作?程序员常有,优秀程序员不常有!

    成为优秀的程序员是极其困难的,并且这个过程不可能一蹴而就. 我们不可能期待去种一些树,然后一夜间收获有着2000年树龄的红杉树,无论其需求有多大. 人格特点 一个人首先得是自学者来学习编程.仅仅是超过 ...