业务需求:BS架构系统的在线更新,实现文件在线校验更新及数据库在线更新。
下面简单写一下思路及实现,整体需包含校验文件及目录配置,文件MD5码校验,文件下载等。其中dll文件的更新需要注意
很多代码是从网上搜来的,项目也没有仔细整理,哪些有用哪些没用也忘记了,干脆全部贴出来,将就着看吧
文件下载类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Threading.Tasks;
namespace YS.Update
{
public class DownFile
{
//从服务器下载文件,若目录存在,直接复制新文件,不存在则新建目录并复制文件,成功后返回1
public bool DownFileFromServ(string url, string fileName)
{
bool downsucess = false;
try
{
string fileExtraName = url.Split(char.Parse("."))[0]; //文件名
string fileAfterName = System.IO.Path.GetExtension(url); //文件的扩展名
if (fileAfterName == ".aspx")
url = fileAfterName + ".txt";
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
myReq.KeepAlive = true;
HttpWebResponse myRes = (HttpWebResponse)myReq.GetResponse();
downsucess = this.CopyFileAndDirectory(myRes, fileName);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
return downsucess;
}
//返回复制文件或创建目录是否成功
public bool CopyFileAndDirectory(WebResponse myResp, string fileName)
{
bool flag = true;
byte[] buffer = new byte[0x400];
try
{
int num;
//若本身已有该目录则删除
if (System.IO.File.Exists(fileName))
{
System.IO.File.Delete(fileName);
}
//创建目录更新到Updat目录下
string directoryName = Path.GetDirectoryName(fileName);
if (!Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
//指定文件fileName不存在时创建它
Stream streamRead = System.IO.File.Open(fileName, FileMode.Create);
Stream responseStream = myResp.GetResponseStream();
do
{
//从当前读取的字节流数,复制
num = responseStream.Read(buffer, 0, buffer.Length);
if (num > 0)
{
streamRead.Write(buffer, 0, num);
}
}
while (num > 0);
streamRead.Close();
responseStream.Close();
}
catch
{
flag = false;
}
return flag;
}
}
}
filehelper
using System;
using System.Text;
using System.IO;
namespace YS.Update
{
public static class FileHelper
{
#region 检测指定目录是否存在
/// <summary>
/// 检测指定目录是否存在
/// </summary>
/// <param name="directoryPath">目录的绝对路径</param>
public static bool IsExistDirectory(string directoryPath)
{
return Directory.Exists(directoryPath);
}
#endregion
#region 检测指定文件是否存在
/// <summary>
/// 检测指定文件是否存在,如果存在则返回true。
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static bool IsExistFile(string filePath)
{
return File.Exists(filePath);
}
#endregion
#region 检测指定目录是否为空
/// <summary>
/// 检测指定目录是否为空
/// </summary>
/// <param name="directoryPath">指定目录的绝对路径</param>
public static bool IsEmptyDirectory(string directoryPath)
{
try
{
//判断是否存在文件
string[] fileNames = GetFileNames(directoryPath);
if (fileNames.Length > 0)
{
return false;
}
//判断是否存在文件夹
string[] directoryNames = GetDirectories(directoryPath);
return directoryNames.Length <= 0;
}
catch
{
return false;
}
}
#endregion
#region 检测指定目录中是否存在指定的文件
/// <summary>
/// 检测指定目录中是否存在指定的文件,若要搜索子目录请使用重载方法.
/// </summary>
/// <param name="directoryPath">指定目录的绝对路径</param>
/// <param name="searchPattern">模式字符串,"*"代表0或N个字符,"?"代表1个字符。
/// 范例:"Log*.xml"表示搜索所有以Log开头的Xml文件。</param>
public static bool Contains(string directoryPath, string searchPattern)
{
try
{
//获取指定的文件列表
string[] fileNames = GetFileNames(directoryPath, searchPattern, false);
//判断指定文件是否存在
return fileNames.Length != 0;
}
catch
{
return false;
}
}
/// <summary>
/// 检测指定目录中是否存在指定的文件
/// </summary>
/// <param name="directoryPath">指定目录的绝对路径</param>
/// <param name="searchPattern">模式字符串,"*"代表0或N个字符,"?"代表1个字符。
/// 范例:"Log*.xml"表示搜索所有以Log开头的Xml文件。</param>
/// <param name="isSearchChild">是否搜索子目录</param>
public static bool Contains(string directoryPath, string searchPattern, bool isSearchChild)
{
try
{
//获取指定的文件列表
string[] fileNames = GetFileNames(directoryPath, searchPattern, true);
//判断指定文件是否存在
return fileNames.Length != 0;
}
catch
{
return false;
}
}
#endregion
#region 创建一个目录
/// <summary>
/// 创建一个目录
/// </summary>
/// <param name="directoryPath">目录的绝对路径</param>
public static void CreateDirectory(string directoryPath)
{
//如果目录不存在则创建该目录
if (!IsExistDirectory(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
}
#endregion
#region 创建一个文件
/// <summary>
/// 创建一个文件。
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static bool CreateFile(string filePath)
{
try
{
//如果文件不存在则创建该文件
if (!IsExistFile(filePath))
{
//创建一个FileInfo对象
FileInfo file = new FileInfo(filePath);
//创建文件
FileStream fs = file.Create();
//关闭文件流
fs.Close();
}
}
catch
{
return false;
}
return true;
}
/// <summary>
/// 创建一个文件,并将字节流写入文件。
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
/// <param name="buffer">二进制流数据</param>
public static bool CreateFile(string filePath, byte[] buffer)
{
try
{
//如果文件不存在则创建该文件
if (!IsExistFile(filePath))
{
//创建一个FileInfo对象
FileInfo file = new FileInfo(filePath);
//创建文件
FileStream fs = file.Create();
//写入二进制流
fs.Write(buffer, 0, buffer.Length);
//关闭文件流
fs.Close();
}
}
catch
{
return false;
}
return true;
}
#endregion
#region 获取文本文件的行数
/// <summary>
/// 获取文本文件的行数
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static int GetLineCount(string filePath)
{
//将文本文件的各行读到一个字符串数组中
string[] rows = File.ReadAllLines(filePath);
//返回行数
return rows.Length;
}
#endregion
#region 获取一个文件的长度
/// <summary>
/// 获取一个文件的长度,单位为Byte
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static int GetFileSize(string filePath)
{
//创建一个文件对象
FileInfo fi = new FileInfo(filePath);
//获取文件的大小
return (int)fi.Length;
}
/// <summary>
/// 获取一个文件的长度,单位为KB
/// </summary>
/// <param name="filePath">文件的路径</param>
public static double GetFileSizeByKB(string filePath)
{
//创建一个文件对象
FileInfo fi = new FileInfo(filePath);
long size = fi.Length / 1024;
//获取文件的大小
return double.Parse(size.ToString());
}
/// <summary>
/// 获取一个文件的长度,单位为MB
/// </summary>
/// <param name="filePath">文件的路径</param>
public static double GetFileSizeByMB(string filePath)
{
//创建一个文件对象
FileInfo fi = new FileInfo(filePath);
long size = fi.Length / 1024 / 1024;
//获取文件的大小
return double.Parse(size.ToString());
}
#endregion
#region 获取指定目录中的文件列表
/// <summary>
/// 获取指定目录中所有文件列表
/// </summary>
/// <param name="directoryPath">指定目录的绝对路径</param>
public static string[] GetFileNames(string directoryPath)
{
//如果目录不存在,则抛出异常
if (!IsExistDirectory(directoryPath))
{
throw new FileNotFoundException();
}
//获取文件列表
return Directory.GetFiles(directoryPath);
}
/// <summary>
/// 获取指定目录及子目录中所有文件列表
/// </summary>
/// <param name="directoryPath">指定目录的绝对路径</param>
/// <param name="searchPattern">模式字符串,"*"代表0或N个字符,"?"代表1个字符。
/// 范例:"Log*.xml"表示搜索所有以Log开头的Xml文件。</param>
/// <param name="isSearchChild">是否搜索子目录</param>
public static string[] GetFileNames(string directoryPath, string searchPattern, bool isSearchChild)
{
//如果目录不存在,则抛出异常
if (!IsExistDirectory(directoryPath))
{
throw new FileNotFoundException();
}
try
{
return Directory.GetFiles(directoryPath, searchPattern, isSearchChild ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
}
catch
{
return null;
}
}
#endregion
#region 获取指定目录中的子目录列表
/// <summary>
/// 获取指定目录中所有子目录列表,若要搜索嵌套的子目录列表,请使用重载方法.
/// </summary>
/// <param name="directoryPath">指定目录的绝对路径</param>
public static string[] GetDirectories(string directoryPath)
{
try
{
return Directory.GetDirectories(directoryPath);
}
catch
{
return null;
}
}
/// <summary>
/// 获取指定目录及子目录中所有子目录列表
/// </summary>
/// <param name="directoryPath">指定目录的绝对路径</param>
/// <param name="searchPattern">模式字符串,"*"代表0或N个字符,"?"代表1个字符。
/// 范例:"Log*.xml"表示搜索所有以Log开头的Xml文件。</param>
/// <param name="isSearchChild">是否搜索子目录</param>
public static string[] GetDirectories(string directoryPath, string searchPattern, bool isSearchChild)
{
try
{
return Directory.GetDirectories(directoryPath, searchPattern, isSearchChild ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
}
catch
{
throw null;
}
}
#endregion
#region 向文本文件写入内容
/// <summary>
/// 向文本文件中写入内容
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
/// <param name="content">写入的内容</param>
public static void WriteText(string filePath, string content)
{
//向文件写入内容
File.WriteAllText(filePath, content);
}
#endregion
#region 向文本文件的尾部追加内容
/// <summary>
/// 向文本文件的尾部追加内容
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
/// <param name="content">写入的内容</param>
public static void AppendText(string filePath, string content)
{
File.AppendAllText(filePath, content);
}
#endregion
#region 将现有文件的内容复制到新文件中
/// <summary>
/// 将源文件的内容复制到目标文件中
/// </summary>
/// <param name="sourceFilePath">源文件的绝对路径</param>
/// <param name="destFilePath">目标文件的绝对路径</param>
public static void Copy(string sourceFilePath, string destFilePath)
{
File.Copy(sourceFilePath, destFilePath, true);
}
#endregion
#region 将文件移动到指定目录
/// <summary>
/// 将文件移动到指定目录
/// </summary>
/// <param name="sourceFilePath">需要移动的源文件的绝对路径</param>
/// <param name="descDirectoryPath">移动到的目录的绝对路径</param>
public static void Move(string sourceFilePath, string descDirectoryPath)
{
//获取源文件的名称
string sourceFileName = GetFileName(sourceFilePath);
if (IsExistDirectory(descDirectoryPath))
{
//如果目标中存在同名文件,则删除
if (IsExistFile(descDirectoryPath + "\\" + sourceFileName))
{
DeleteFile(descDirectoryPath + "\\" + sourceFileName);
}
//将文件移动到指定目录
File.Move(sourceFilePath, descDirectoryPath + "\\" + sourceFileName);
}
}
#endregion
#region 将流读取到缓冲区中
/// <summary>
/// 将流读取到缓冲区中
/// </summary>
/// <param name="stream">原始流</param>
public static byte[] StreamToBytes(Stream stream)
{
try
{
//创建缓冲区
byte[] buffer = new byte[stream.Length];
//读取流
stream.Read(buffer, 0, int.Parse(stream.Length.ToString()));
//返回流
return buffer;
}
catch
{
return null;
}
finally
{
//关闭流
stream.Close();
}
}
#endregion
#region 将文件读取到缓冲区中
/// <summary>
/// 将文件读取到缓冲区中
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static byte[] FileToBytes(string filePath)
{
//获取文件的大小
int fileSize = GetFileSize(filePath);
//创建一个临时缓冲区
byte[] buffer = new byte[fileSize];
//创建一个文件流
FileInfo fi = new FileInfo(filePath);
FileStream fs = fi.Open(FileMode.Open);
try
{
//将文件流读入缓冲区
fs.Read(buffer, 0, fileSize);
return buffer;
}
catch
{
return null;
}
finally
{
//关闭文件流
fs.Close();
}
}
#endregion
#region 将文件读取到字符串中
/// <summary>
/// 将文件读取到字符串中
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static string FileToString(string filePath)
{
return FileToString(filePath, Encoding.Default);
}
/// <summary>
/// 将文件读取到字符串中
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
/// <param name="encoding">字符编码</param>
public static string FileToString(string filePath, Encoding encoding)
{
//创建流读取器
StreamReader reader = new StreamReader(filePath, encoding);
try
{
//读取流
return reader.ReadToEnd();
}
catch
{
return string.Empty;
}
finally
{
//关闭流读取器
reader.Close();
}
}
#endregion
#region 从文件的绝对路径中获取文件名( 包含扩展名 )
/// <summary>
/// 从文件的绝对路径中获取文件名( 包含扩展名 )
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static string GetFileName(string filePath)
{
//获取文件的名称
FileInfo fi = new FileInfo(filePath);
return fi.Name;
}
#endregion
#region 从文件的绝对路径中获取文件名( 不包含扩展名 )
/// <summary>
/// 从文件的绝对路径中获取文件名( 不包含扩展名 )
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static string GetFileNameNoExtension(string filePath)
{
//获取文件的名称
FileInfo fi = new FileInfo(filePath);
return fi.Name.Split('.')[0];
}
#endregion
#region 从文件的绝对路径中获取扩展名
/// <summary>
/// 从文件的绝对路径中获取扩展名
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static string GetExtension(string filePath)
{
//获取文件的名称
FileInfo fi = new FileInfo(filePath);
return fi.Extension;
}
#endregion
#region 清空指定目录
/// <summary>
/// 清空指定目录下所有文件及子目录,但该目录依然保存.
/// </summary>
/// <param name="directoryPath">指定目录的绝对路径</param>
public static void ClearDirectory(string directoryPath)
{
if (IsExistDirectory(directoryPath))
{
//删除目录中所有的文件
string[] fileNames = GetFileNames(directoryPath);
foreach (string t in fileNames)
{
DeleteFile(t);
}
//删除目录中所有的子目录
string[] directoryNames = GetDirectories(directoryPath);
foreach (string t in directoryNames)
{
DeleteDirectory(t);
}
}
}
#endregion
#region 清空文件内容
/// <summary>
/// 清空文件内容
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static void ClearFile(string filePath)
{
//删除文件
File.Delete(filePath);
//重新创建该文件
CreateFile(filePath);
}
#endregion
#region 删除指定文件
/// <summary>
/// 删除指定文件
/// </summary>
/// <param name="filePath">文件的绝对路径</param>
public static void DeleteFile(string filePath)
{
if (IsExistFile(filePath))
{
File.Delete(filePath);
}
}
#endregion
#region 删除指定目录
/// <summary>
/// 删除指定目录及其所有子目录
/// </summary>
/// <param name="directoryPath">指定目录的绝对路径</param>
public static void DeleteDirectory(string directoryPath)
{
if (IsExistDirectory(directoryPath))
{
Directory.Delete(directoryPath, true);
}
}
#endregion
#region 记录错误日志到文件方法
/// <summary>
/// 记录错误日志到文件方法
/// </summary>
/// <param name="exMessage"></param>
/// <param name="exMethod"></param>
/// <param name="userID"></param>
public static void ErrorLog(string exMessage, string exMethod, int userID)
{
try
{
string errVir = "/Log/Error/" + DateTime.Now.ToShortDateString() + ".txt";
string errPath = System.Web.HttpContext.Current.Server.MapPath(errVir);
File.AppendAllText(errPath,
"{userID:" + userID + ",exMedthod:" + exMethod + ",exMessage:" + exMessage + "}");
}
catch
{
}
}
#endregion
#region 输出调试日志
/// <summary>
/// 输出调试日志
/// </summary>
/// <param name="factValue">实际值</param>
/// <param name="expectValue">预期值</param>
public static void OutDebugLog(object factValue, object expectValue = null)
{
string errPath = System.Web.HttpContext.Current.Server.MapPath(string.Format("/Log/Debug/{0}.html", DateTime.Now.ToShortDateString()));
if (!Equals(expectValue, null))
File.AppendAllLines(errPath,
new[]{string.Format(
"【{0}】[{3}] 实际值:<span style='color:blue;'>{1}</span> 预期值: <span style='color:gray;'>{2}</span><br/>",
DateTime.Now.ToShortTimeString()
, factValue, expectValue, Equals(expectValue, factValue)
? "<span style='color:green;'>成功</span>"
: "<span style='color:red;'>失败</span>")});
else
File.AppendAllLines(errPath, new[]{
string.Format(
"【{0}】[{3}] 实际值:<span style='color:blue;'>{1}</span> 预期值: <span style='color:gray;'>{2}</span><br/>",
DateTime.Now.ToShortTimeString()
, factValue, "空", "<span style='color:green;'>成功</span>")});
}
#endregion
}
}
JSON
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using System.Data;
namespace YS.Update
{
/// <summary>
/// JSON帮助类
/// </summary>
public class json
{
/// <summary>
/// 对象转JSON
/// </summary>
/// <param name="obj">对象</param>
/// <returns>JSON格式的字符串</returns>
public static string ObjectToJSON(object obj)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
try
{
byte[] b = Encoding.UTF8.GetBytes(jss.Serialize(obj));
return Encoding.UTF8.GetString(b);
}
catch (Exception ex)
{
throw new Exception("JSONHelper.ObjectToJSON(): " + ex.Message);
}
}
/// <summary>
/// 数据表转键值对集合
/// 把DataTable转成 List集合, 存每一行
/// 集合中放的是键值对字典,存每一列
/// </summary>
/// <param name="dt">数据表</param>
/// <returns>哈希表数组</returns>
public static List<Dictionary<string, object>> DataTableToList(DataTable dt)
{
List<Dictionary<string, object>> list
= new List<Dictionary<string, object>>();
foreach (DataRow dr in dt.Rows)
{
Dictionary<string, object> dic = new Dictionary<string, object>();
foreach (DataColumn dc in dt.Columns)
{
dic.Add(dc.ColumnName, dr[dc.ColumnName]);
}
list.Add(dic);
}
return list;
}
/// <summary>
/// 数据集转键值对数组字典
/// </summary>
/// <param name="dataSet">数据集</param>
/// <returns>键值对数组字典</returns>
public static Dictionary<string, List<Dictionary<string, object>>> DataSetToDic(DataSet ds)
{
Dictionary<string, List<Dictionary<string, object>>> result = new Dictionary<string, List<Dictionary<string, object>>>();
foreach (DataTable dt in ds.Tables)
result.Add(dt.TableName, DataTableToList(dt));
return result;
}
/// <summary>
/// 数据表转JSON
/// </summary>
/// <param name="dataTable">数据表</param>
/// <returns>JSON字符串</returns>
public static string DataTableToJSON(DataTable dt)
{
return ObjectToJSON(DataTableToList(dt));
}
/// <summary>
/// JSON文本转对象,泛型方法
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <param name="jsonText">JSON文本</param>
/// <returns>指定类型的对象</returns>
public static T JSONToObject<T>(string jsonText)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
try
{
return jss.Deserialize<T>(jsonText);
}
catch (Exception ex)
{
throw new Exception("JSONHelper.JSONToObject(): " + ex.Message);
}
}
/// <summary>
/// 将JSON文本转换为数据表数据
/// </summary>
/// <param name="jsonText">JSON文本</param>
/// <returns>数据表字典</returns>
public static Dictionary<string, List<Dictionary<string, object>>> TablesDataFromJSON(string jsonText)
{
return JSONToObject<Dictionary<string, List<Dictionary<string, object>>>>(jsonText);
}
/// <summary>
/// 将JSON文本转换成数据行
/// </summary>
/// <param name="jsonText">JSON文本</param>
/// <returns>数据行的字典</returns>
public static Dictionary<string, object> DataRowFromJSON(string jsonText)
{
return JSONToObject<Dictionary<string, object>>(jsonText);
}
}
}
XML处理类
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Net;
using System.IO;
namespace YS.Update
{
public class XmlHelper
{
#region 增、删、改操作==============================================
/// <summary>
/// 追加节点
/// </summary>
/// <param name="filePath">XML文档绝对路径</param>
/// <param name="xPath">范例: @"Skill/First/SkillItem"</param>
/// <param name="xmlNode">XmlNode节点</param>
/// <returns></returns>
public static bool AppendChild(string filePath, string xPath, XmlNode xmlNode)
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlNode xn = doc.SelectSingleNode(xPath);
XmlNode n = doc.ImportNode(xmlNode, true);
xn.AppendChild(n);
doc.Save(filePath);
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 从XML文档中读取节点追加到另一个XML文档中
/// </summary>
/// <param name="filePath">需要读取的XML文档绝对路径</param>
/// <param name="xPath">范例: @"Skill/First/SkillItem"</param>
/// <param name="toFilePath">被追加节点的XML文档绝对路径</param>
/// <param name="toXPath">范例: @"Skill/First/SkillItem"</param>
/// <returns></returns>
public static bool AppendChild(string filePath, string xPath, string toFilePath, string toXPath)
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(toFilePath);
XmlNode xn = doc.SelectSingleNode(toXPath);
XmlNodeList xnList = ReadNodes(filePath, xPath);
if (xnList != null)
{
foreach (XmlElement xe in xnList)
{
XmlNode n = doc.ImportNode(xe, true);
xn.AppendChild(n);
}
doc.Save(toFilePath);
}
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 修改节点的InnerText的值
/// </summary>
/// <param name="filePath">XML文件绝对路径</param>
/// <param name="xPath">范例: @"Skill/First/SkillItem"</param>
/// <param name="value">节点的值</param>
/// <returns></returns>
public static bool UpdateNodeInnerText(string filePath, string xPath, string value)
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlNode xn = doc.SelectSingleNode(xPath);
XmlElement xe = (XmlElement)xn;
xe.InnerText = value;
doc.Save(filePath);
}
catch
{
return false;
}
return true;
}
/// <summary>
/// 读取XML文档
/// </summary>
/// <param name="filePath">XML文件绝对路径</param>
/// <returns></returns>
public static XmlDocument LoadXmlDoc(string filePath)
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
return doc;
}
catch
{
return null;
}
}
#endregion 增、删、改操作
#region 扩展方法===================================================
/// <summary>
/// 读取XML的所有子节点
/// </summary>
/// <param name="filePath">XML文件绝对路径</param>
/// <param name="xPath">范例: @"Skill/First/SkillItem"</param>
/// <returns></returns>
public static XmlNodeList ReadNodes(string filePath, string xPath)
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlNode xn = doc.SelectSingleNode(xPath);
XmlNodeList xnList = xn.ChildNodes; //得到该节点的子节点
return xnList;
}
catch
{
return null;
}
}
///<summary>
/// 加载远程XML文档
///</summary>
///<param name="URL"></param>
///<returns></returns>
public static XmlDocument loadxml(string URL)
{
//使用rssURL的值建立了一个WebRequest项
WebRequest myRequest = WebRequest.Create(URL);
//WebRequest请求的响应将会被放到一个WebResponse对象myResponse里,然后这个WebResponse对象被用来建立一个流来取出XML的值
try
{
WebResponse myResponse = myRequest.GetResponse();
Stream stream = myResponse.GetResponseStream();
//使用一个XmlDocument对象rssDoc来存储流中的XML内容。XmlDocument对象用来调入XML的内容
XmlDocument doc = new XmlDocument();
doc.Load(stream);
return doc;
}
catch
{
return null;
}
}
#endregion 扩展方法
}
}
update.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Threading.Tasks;
namespace YS.Update
{
/// <summary>
/// 需要如下方法
/// 1.获取文件MD5
/// 2.获取远程文件
/// 3.对比本地文件MD5
/// 4.替换本地文件
/// 5.文件缓存处理
/// 6.本地文件自动备份
/// 7.更新文件列表
/// 8.数据库更新文件缓存
/// </summary>
public class update
{
public string url = null;
public string cmd = null;
public bool flag = false;
public static string GetMD5Hash(string fileName)
{
try
{
FileStream file = new FileStream(fileName, FileMode.Open);
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(file);
file.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
catch (Exception ex)
{
throw new Exception("GetMD5Hash() fail,error:" + ex.Message);
}
}
/// <summary>
/// 读取配置文件
/// </summary>
public update()
{
string path = AppDomain.CurrentDomain.BaseDirectory + "xmlconfig/update.xml";
try
{
if (path != null)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(path);
url = xmlDoc.SelectSingleNode("/update/url").InnerText;
}
}
catch (Exception ex)
{
throw new Exception("找不到autoUpdate.xml文件" + ex.Message);
}
}
//获取服务器的版本
public Version GetServerVersion()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(url);
return new Version(xmlDoc.SelectSingleNode("/update/version").InnerText);
}
//获取客户端版本
public string GetClientVersion()
{
url = AppDomain.CurrentDomain.BaseDirectory + "userVersion.xml";
XmlDocument xmlUser = new XmlDocument();
xmlUser.Load(url);
XmlElement root = xmlUser.DocumentElement;
XmlNode updateNode = root.SelectSingleNode("version");
string version = updateNode.Attributes["value"].Value;
return version;
}
//为了进行版本比较,进行转换为整数比较
public int ConvertVersion(string value)
{
int w, z, x, y, temp;
w = int.Parse(value.Substring(0, 1));
z = int.Parse(value.Substring(2, 1));
x = int.Parse(value.Substring(4, 1));
y = int.Parse(value.Substring(6, 1));
temp = w * 1000 + z * 100 + x * 10 + y;
return temp;
}
//更新客户版本号为服务器的版本号
public string UpdateVersion(string serVersion)
{
url = AppDomain.CurrentDomain.BaseDirectory + "userVersion.xml";
XmlDocument xmlUser = new XmlDataDocument();
xmlUser.Load(url);
XmlElement root = xmlUser.DocumentElement;
XmlNode updateNode = root.SelectSingleNode("version");
string strVer = updateNode.Attributes["value"].Value;
updateNode.Attributes["value"].Value = serVersion;
xmlUser.Save(url);
return serVersion;
}
/// <summary>
///从服务器文件update.xml中获取要下载的文件列表
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public string[] GetFileList(string url)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(url);
XmlElement root = xmlDoc.DocumentElement;
XmlNode updateNode = root.SelectSingleNode("filelist");
string soucePath = updateNode.Attributes["sourcepath"].Value;
string fileName = null;
string fileList = null;
//取出服务器里update.xml里更新的file文件
XmlNodeList fileNode = updateNode.SelectNodes("file");
if (fileNode != null)
{
foreach (XmlNode i in fileNode)
{
foreach (XmlNode j in i)
{
if (i.Attributes["filesname"].Value != "")
fileName = soucePath + i.Attributes["filesname"].Value + "/" + j.Attributes["name"].Value +
"$" + i.Attributes["filesname"].Value + "/" + j.Attributes["name"].Value;
else
fileName = soucePath + j.Attributes["name"].Value +
"$" + j.Attributes["name"].Value;
fileName += ",";
fileList += fileName;
}
}
string[] splitFile = fileList.Split(',');
flag = true;
return splitFile;
}
return null;
}
}
[Serializable]
public partial class filemodel
{
public filemodel()
{ }
private string _filename;
public string filename
{
get { return _filename; }
set { _filename = value; }
}
}
[Serializable]
public partial class sqlmodel
{
public sqlmodel()
{ }
private string _tablename;
private string _sqlid;
private string _sql;
public string tablename
{
get { return _tablename; }
set { _tablename = value; }
}
public string sqlid
{
get { return _sqlid; }
set { _sqlid = value; }
}
public string sql
{
get { return _sql; }
set { _sql = value; }
}
}
}
update 后端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Net;
using System.IO;
using System.Web;
using System.Security.Cryptography;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Data.Common;
using System.Text.RegularExpressions;
namespace YS.Update.page
{
public partial class goupdate : System.Web.UI.Page
{
protected string updateurl = "";
XmlDocument xmldoc = null;
protected static int f_num = 0;
protected static int s_num = 0;
protected static int c_num = 0;
protected static List<filemodel> flist = new List<filemodel>();
protected static List<sqlmodel> qlist = new List<sqlmodel>();
protected void Page_Load(object sender, EventArgs e)
{
xmldoc = XmlHelper.LoadXmlDoc(Server.MapPath(@"~/xmlconfig/versioncach.xml"));
if (!IsPostBack)
{
XmlNode url = xmldoc.SelectSingleNode(@"root/url");
if (url == null || url.InnerText == "")
{
Response.Write("参数丢失,请联系管理员");
Response.End();
}
updateurl = url.InnerText;
}
if (Request.QueryString["action"] == "checkupdate")
{
checkupdate();
return;
}
if (Request.QueryString["action"] == "resfile")
{
resfile();
return;
}
if (Request.QueryString["action"] == "process")
{
process();
return;
}
}
/// <summary>
/// 写cookie值
/// </summary>
/// <param name="strName">名称</param>
/// <param name="strValue">值</param>
public static void WriteCookie(string strName, string strValue)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[strName];
if (cookie == null)
{
cookie = new HttpCookie(strName);
}
cookie.Value = UrlEncode(strValue);
HttpContext.Current.Response.AppendCookie(cookie);
}
/// <summary>
/// 读cookie值
/// </summary>
/// <param name="strName">名称</param>
/// <returns>cookie值</returns>
public static string GetCookie(string strName)
{
if (HttpContext.Current.Request.Cookies != null && HttpContext.Current.Request.Cookies[strName] != null)
return UrlDecode(HttpContext.Current.Request.Cookies[strName].Value.ToString());
return "";
}
/// <summary>
/// URL字符编码
/// </summary>
public static string UrlEncode(string str)
{
if (string.IsNullOrEmpty(str))
{
return "";
}
str = str.Replace("'", "");
return HttpContext.Current.Server.UrlEncode(str);
}
/// <summary>
/// URL字符解码
/// </summary>
public static string UrlDecode(string str)
{
if (string.IsNullOrEmpty(str))
{
return "";
}
return HttpContext.Current.Server.UrlDecode(str);
}
private void checkupdate()
{
f_num = 0;
s_num = 0;
c_num = 0;
flist.Clear();
qlist.Clear();
WriteCookie("c_num","0");
XmlDocument newfile = XmlHelper.loadxml(updateurl+"xmlconfig/update.xml");
if (newfile == null)
{
Response.Write("{\"status\": 0, \"msg\": \"\"}");
}
XmlNode xn = newfile.SelectSingleNode(@"root/checkfiles");
XmlNodeList xnList = xn.ChildNodes; //得到该节点的子节点
XmlNode ckfnote = xmldoc.SelectSingleNode(@"root/checkfiles");
ckfnote.RemoveAll();//移除旧数据
foreach (XmlNode item in xnList)
{
string url=item.Attributes["name"].Value;
if (!FileHelper.IsExistFile(Server.MapPath("/" + url)))
{
XmlElement newnote = xmldoc.CreateElement("file");
newnote.InnerText = item.Attributes["name"].Value;
ckfnote.AppendChild(newnote);
filemodel fm = new filemodel();
fm.filename = item.Attributes["name"].Value;
flist.Add(fm);
f_num++;
}
else
{
string md5 = update.GetMD5Hash(Server.MapPath("/" + url));
if (md5 != item.Attributes["md5"].Value)
{
XmlElement newnote = xmldoc.CreateElement("file");
newnote.InnerText = item.Attributes["name"].Value;
ckfnote.AppendChild(newnote);
filemodel fm = new filemodel();
fm.filename = item.Attributes["name"].Value;
flist.Add(fm);
f_num++;
}
}
}
XmlNode sqlnote = xmldoc.SelectSingleNode(@"root/sqlupdate");
XmlNode xn1 = newfile.SelectSingleNode(@"root/sqlupdate");
XmlNodeList xnList1 = xn1.ChildNodes; //得到该节点的子节点
foreach (XmlNode item in xnList1)
{
if (sqlnote.SelectSingleNode("//sql[@sqlid='" + item.Attributes["sqlid"].Value + "']")==null)
{
XmlNode n = xmldoc.ImportNode(item, true);
sqlnote.AppendChild(n);
}
}
foreach (XmlNode item in sqlnote)
{
if (item.Attributes["isrun"].Value.ToString() == "0")
{
sqlmodel sm = new sqlmodel();
sm.tablename = item.Attributes["tablename"].Value;
sm.sqlid = item.Attributes["sqlid"].Value;
qlist.Add(sm);
s_num++;
}
}
///下载文件测试
//DownFileFromServ(updateurl + "admin/update/update.aspx?action=resfile&file=/bin/DTcms.Web.dll", AppDomain.CurrentDomain.BaseDirectory + "/test/DTcms.Web.dll");
///
xmldoc.Save(Server.MapPath(@"~/xmlconfig/versioncach.xml"));
Response.Write("{\"status\": 1, \"files\": " + json.ObjectToJSON(flist) + ",\"sqls\":"+json.ObjectToJSON(qlist)+"}");
Response.End();
}
private void getflist()
{
flist.Clear();
qlist.Clear();
XmlDocument doc = XmlHelper.LoadXmlDoc(Server.MapPath(@"~/xmlconfig/versioncach.xml"));
XmlNode sqlnote = xmldoc.SelectSingleNode(@"root/sqlupdate");
XmlNodeList xnList1 = sqlnote.ChildNodes;
foreach (XmlNode item in sqlnote)
{
if (item.Attributes["isrun"].Value.ToString() == "0")
{
sqlmodel sm = new sqlmodel();
sm.tablename = item.Attributes["tablename"].Value;
sm.sqlid = item.Attributes["sqlid"].Value;
sm.sql = item.InnerText;
qlist.Add(sm);
}
}
XmlNode ckfnote = doc.SelectSingleNode(@"root/checkfiles");
XmlNodeList xnList = ckfnote.ChildNodes;
foreach (XmlNode item in xnList)
{
filemodel fm = new filemodel();
fm.filename = item.InnerText;
flist.Add(fm);
}
}
private void process()
{
XmlDocument doc = XmlHelper.LoadXmlDoc(Server.MapPath(@"~/xmlconfig/versioncach.xml"));
if (doc == null)
{
Response.End();
return;
}
string type = Request.Form["type"];
if (type == "file")
{
getflist();
c_num =Int32.Parse(GetCookie("c_num"));
if (flist.Count == c_num)
{
Response.Write("{\"status\":0,\"result\":{\"total\": " + flist.Count + ", \"success\": " + c_num + ",\"action\":\"file\"}}");
WriteCookie("c_num", "0");
c_num = 0;
Response.End();
return;
}
if (DownFileFromServ(updateurl + "admin/update/update.aspx?action=resfile&file=/" + flist[c_num].filename, AppDomain.CurrentDomain.BaseDirectory + "/" + flist[c_num].filename))
{
c_num++;
WriteCookie("c_num", c_num.ToString());
Response.Write("{\"status\":1,\"result\":{\"total\": " + flist.Count + ", \"success\": " + c_num + ",\"action\":\"file\"}}");
Response.End();
return;
}
else
{
c_num++;
WriteCookie("c_num", c_num.ToString());
Response.Write("{\"status\":2,\"result\":{\"total\": " + flist.Count + ", \"emsg\": \"更新文件失败,请联系管理员!\",\"action\":\"file\"}}");
Response.End();
return;
}
}
if (type == "database")
{
getflist();
c_num = Int32.Parse(GetCookie("c_num"));
if (qlist.Count == c_num)
{
Response.Write("{\"status\":0,\"result\":{\"total\": " + qlist.Count + ", \"success\": " + c_num + ",\"action\":\"database\"}}");
WriteCookie("c_num", "0");
c_num = 0;
Response.End();
return;
}
if (ExecuteSqlWithGo(qlist[c_num].sql))
{
XmlNode sqlnote = doc.SelectSingleNode(@"root/sqlupdate");
XmlElement note1 = (XmlElement)sqlnote.SelectSingleNode("//sql[@sqlid='" + qlist[c_num].sqlid + "']");
note1.SetAttribute("isrun", "1");
doc.Save(Server.MapPath(@"~/xmlconfig/versioncach.xml"));
c_num++;
WriteCookie("c_num", c_num.ToString());
Response.Write("{\"status\":1,\"result\":{\"total\": " + qlist.Count + ", \"success\": " + c_num + ",\"action\":\"database\"}}");
Response.End();
return;
}
else
{
c_num++;
WriteCookie("c_num", c_num.ToString());
Response.Write("{\"status\":2,\"result\":{\"total\": " + qlist.Count + ", \"emsg\": \"更新数据库失败,请联系管理员!\",\"action\":\"database\"}}");
Response.End();
return;
}
}
}
public static bool ExecuteSqlWithGo(String sql)
{
int effectedRows = 0;
string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
try
{
//注: 此处以 换行_后面带0到多个空格_再后面是go 来分割字符串
String[] sqlArr = Regex.Split(sql.Trim(), "\r\n\\s*go", RegexOptions.IgnoreCase);
foreach (string strsql in sqlArr)
{
if (strsql.Trim().Length > 1 && strsql.Trim() != "\r\n")
{
cmd.CommandText = strsql;
effectedRows = cmd.ExecuteNonQuery();
}
}
return true;
}
catch (System.Data.SqlClient.SqlException E)
{
return false;
}
finally
{
conn.Close();
}
}
}
private void resfile()
{
string fileurl = Request.QueryString["file"];
if (fileurl == "")
{
return;
}
Response.WriteFile(Server.MapPath(fileurl));
Response.End();
}
public bool DownFileFromServ(string url, string fileName)
{
bool downsucess = false;
try
{
string fileExtraName = url.Split(char.Parse("."))[0]; //文件名
string fileAfterName = System.IO.Path.GetExtension(url); //文件的扩展名
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
myReq.KeepAlive = true;
HttpWebResponse myRes = (HttpWebResponse)myReq.GetResponse();
downsucess = this.CopyFileAndDirectory(myRes, fileName);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
return downsucess;
}
//返回复制文件或创建目录是否成功
public bool CopyFileAndDirectory(WebResponse myResp, string fileName)
{
bool flag = true;
byte[] buffer = new byte[0x400];
try
{
int num;
//若本身已有该目录则删除
if (System.IO.File.Exists(fileName))
{
System.IO.File.Delete(fileName);
}
//创建目录更新到Updat目录下
string directoryName = Path.GetDirectoryName(fileName);
if (!Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
//指定文件fileName不存在时创建它
Stream streamRead = System.IO.File.Open(fileName, FileMode.Create);
Stream responseStream = myResp.GetResponseStream();
do
{
//从当前读取的字节流数,复制
num = responseStream.Read(buffer, 0, buffer.Length);
if (num > 0)
{
streamRead.Write(buffer, 0, num);
}
}
while (num > 0);
streamRead.Close();
responseStream.Close();
}
catch
{
flag = false;
}
return flag;
}
}
}
update页面前端
<%@ Page Language="C#" AutoEventWireup="true" Inherits="YS.Update.page.goupdate" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="/admin/js/util.js"></script>
<link href="../skin/common.css" rel="stylesheet" />
<style>
.upgrade-info{width:80%; margin:auto;}
</style>
</head>
<body>
<form id="form1" runat="server" class="form we7-form">
<div style="text-align:center; padding-top:100px;" id="stp1">
<div id="tips"></div>
</div>
<div class="upgrade-info we7-padding-bottom" hidden="true">
<div class="panel we7-panel">
<div class="panel-heading we7-padding">
<span class="col-sm-2 we7-padding-none color-gray">发现新版本可以更新</span>
</div>
<div class="panel-body we7-padding">
<div class="form-group">
<label for="" class="control-label color-gray col-sm-2">需要更新文件</label>
<div class="form-controls col-sm-7 form-control-static"><span id="file_num"></span> 个</div>
<span class="color-default col-sm-3 text-right"><a href="#upgrade-file" data-toggle="modal" >查看</a></span>
</div>
<div class="form-group">
<label for="" class="control-label color-gray col-sm-2">需要更新数据库</label>
<div class="form-controls col-sm-7 form-control-static"><span id="sql_num"></span> 项</div>
<span class="color-default col-sm-3 text-right"><a href="#upgrade-databases" data-toggle="modal" >查看</a></span>
</div>
<div class="form-group we7-padding-none">
</div>
</div>
</div>
<div class="text-center">
<input type="button" name="" id="forward" value="一键更新" class="btn btn-danger" />
<input type="button" name="" id="process" value="正在更新,请不要关闭浏览器" class="btn btn-danger" style="display:none;" />
<div id="emsg" style="color:red;"></div>
</div>
</div>
<div class="modal fade" id="upgrade-file" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog we7-modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span>
</button>
<h4 class="modal-title">更新文件</h4>
</div>
<div class="modal-body color-dark" id="file_list">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">确定</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="upgrade-databases" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog we7-modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span>
</button>
<h4 class="modal-title">更新数据库</h4>
</div>
<div class="modal-body color-dark" id="sql_list">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">确定</button>
</div>
</div>
</div>
</div
</form>
</body>
</html>
<script type="text/javascript">
$(function () {
getupdate();
})
$('#forward').click(function () {
var a = $("#agreement_0").is(':checked');
var b = $("#agreement_1").is(':checked');
if (confirm('更新将直接覆盖本地文件, 请注意备份文件和数据. \n\n**另注意** 更新过程中不要关闭此浏览器窗口.')) {
// location.href = './index.php?c=cloud&a=process&';
$("#forward").hide();
$("#process").show();
process("file");
}
});
function process(action) {
$.ajax({
url: "/updatecach.aspx?action=process",
data: { type: action },
type: 'post',
dataType: 'json',
success: function (ret) {
var status = ret.status;
var result = ret.result;
var act = result.action;
console.log(ret);
if (act == 'database') {
if (status == 1) {
$('#process').val("已更新 " + result.success + " 条数据库结构变动 / 共 " + result.total + " 条");
process('database');
}
else if (status == 2) {
$("#emsg").append("<div>" + result.emsg + "</div>");
process('database');
}
else {
$('#process').val("已成功更新 " + result.total + " 条数据库结构变动");
$('#process').val('更新成功');
alert("更新成功,如有错误信息请联系管理员解决");
location.reload();
}
} else if (act == 'file') {
if (status == 1) {
$('#process').val("已更新 " + result.success + " 个文件 / 共 " + result.total + " 个文件");
process('file');
} else if (status == 2) {
$("#emsg").append("<div>" + result.emsg + "</div>");
process('file');
} else {
$('#process').val("已成功更新 " + result.total + " 个文件");
process('database');
}
}
}
});
}
function getupdate() {
$("#tips").html("正在检测新版本,请耐心等待");
$.ajax({
url: "/admin/update/update.aspx?action=checkupdate",
type: 'post',
dataType: 'json',
success: function (ret) {
console.log(ret);
if (ret.status == 0)
{
util.message("检测更新失败,请联系管理员", '', 'error');
}
if (ret.status == 1) {
var html = "";
if (ret.files.length <= 0 && ret.sqls.length <= 0) {
html = "恭喜您,您现在是最新版本!";
$("#tips").html(html);
} else {//更新显示逻辑
$("#stp1").hide();
$("#file_num").html(ret.files.length);
$("#sql_num").html(ret.sqls.length);
$(".upgrade-info").show();
for (var i = 0; i < ret.files.length; i++)
{
html += "<div>" + ret.files [i].filename+ "</div>";
}
$("#file_list").html(html);
html = "";
for (var i = 0; i < ret.sqls.length; i++) {
html += "<div>" + ret.sqls[i].tablename + "</div>";
}
$("#sql_list").html(html);
}
}
}
})
}
</script>
makeupdate 页面后端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace YS.Update.page
{
public partial class makeupdate : System.Web.UI.Page
{
protected global::System.Web.UI.HtmlControls.HtmlGenericControl msgtip;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
msgtip.InnerHtml = "正在处理数据,请稍后...";
string baseurl = System.AppDomain.CurrentDomain.BaseDirectory;
XmlDocument xmldoc = XmlHelper.LoadXmlDoc(Server.MapPath(@"~/xmlconfig/update.xml"));
XmlNode ckfnote = xmldoc.SelectSingleNode(@"root/checkfiles");
ckfnote.RemoveAll();//移除旧数据
XmlNodeList folderlist = XmlHelper.ReadNodes(Server.MapPath(@"~/xmlconfig/update.xml"), @"root/folders");//文件夹列表
if (folderlist != null)
{
foreach (XmlNode i in folderlist)
{
if (FileHelper.IsExistDirectory(Server.MapPath(i.InnerText)))
{
string[] filelist = FileHelper.GetFileNames(Server.MapPath(i.InnerText), "*", true);
List<string> list = filelist.Where(s => s.ToLower().EndsWith(".aspx") || s.ToLower().EndsWith(".css") || s.ToLower().EndsWith(".js") || s.ToLower().EndsWith(".html") || s.ToLower().EndsWith(".xml") || s.ToLower().EndsWith(".ashx") || s.ToLower().EndsWith(".dll")).ToList();
foreach (string item in list)
{
string md5 = update.GetMD5Hash(item);
string fileurl = item.Replace(baseurl, "");
XmlElement newnote = xmldoc.CreateElement("file");
newnote.SetAttribute("name",fileurl);
newnote.SetAttribute("md5",md5);
ckfnote.AppendChild(newnote);
}
}
}
}
XmlNodeList files = XmlHelper.ReadNodes(Server.MapPath(@"~/xmlconfig/update.xml"), @"root/files");//文件列表
if (files != null)
{
foreach (XmlNode i in files)
{
if (FileHelper.IsExistFile(Server.MapPath(i.InnerText)))
{
string md5 = update.GetMD5Hash(Server.MapPath(i.InnerText));
string fileurl = Server.MapPath(i.InnerText).Replace(baseurl, "");
XmlElement newnote = xmldoc.CreateElement("file");
newnote.SetAttribute("name", fileurl);
newnote.SetAttribute("md5", md5);
ckfnote.AppendChild(newnote);
}
}
}
xmldoc.Save(Server.MapPath(@"~/xmlconfig/update.xml"));
msgtip.InnerHtml = "更新版本配置文件成功,如有数据库更新请手动修改配置文件";
}
}
}
makeupdate页面前端
<%@ Page Language="C#" AutoEventWireup="true" Inherits="YS.Update.page.makeupdate" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<style>
.btn{margin:auto; width:250px; height:50px;}
</style>
<body>
<form id="form1" runat="server">
<div style="text-align:center; padding-top:100px;">
<asp:Button ID="btnSubmit" runat="server" Text="更新版本服务端数据" CssClass="btn" onclick="btnSubmit_Click" />
<p id="msgtip" runat="server"></p>
</div>
</form>
</body>
</html>
versioncach.xml
<?xml version="1.0" encoding="utf-8"?>
<root>
<url>http://127.0.0.1/</url>
<sqlupdate>
</sqlupdate>
<checkfiles>
<file>aspx\wxapp\repassword.aspx</file>
</checkfiles>
</root>
update.xml 用于存储校验配置及文件特征
<?xml version="1.0" encoding="utf-8"?>
<root>
<version>1.0.1.9</version>
<url>http://test.yunbaokai.com/</url>
<folders>
<folder>/admin/</folder>
<folder>/api/</folder>
<folder>/bin/</folder>
<folder>/css/</folder>
<folder>/dialog/</folder>
<folder>/editor/</folder>
<folder>/scripts/</folder>
<folder>/tools/</folder>
<folder>/aspx/</folder>
<folder>/templates/</folder>
</folders>
<files>
<file>/get_yhq.aspx</file>
<file>/postgo.aspx</file>
</files>
<sqlupdate>
<sql tablename="test" sqlid="1" isrun="0"><![CDATA[
if not exists (select * from sysobjects where id = object_id('mytab') and OBJECTPROPERTY(id, 'IsUserTable') = 1)
create table mytab
(
id int,
age int ,
name varchar(max),
primary key (id,age)
)
]]></sql>
</sqlupdate>
<checkfiles>
<file name="admin\center.aspx" md5="1e1742090e34d9b7baba5a8930e6c641" />
<file name="admin\ie6update.html" md5="48f37c02cd5ad9e04b2ea815c0041723" />
<file name="admin\index.aspx" md5="546dd4a4ae928308923c598ea75b6f9d" />
<file name="admin\login.aspx" md5="cceaf8ce293d3fb0281ed462be53bff9" />
<file name="admin\logout.aspx" md5="0b66270bec9d59777bdf56895d690981" />
<file name="admin\mlogin.aspx" md5="94ba2a49786124d558c9e0497e30fc61" />
<file name="admin\article\article_dan.aspx" md5="84f6959702ceda4f7e0eaaa1de1e0c46" />
</checkfiles>
</root>