base64+博文与程序更新

来源:互联网 发布:stc89c52烧录软件 编辑:程序博客网 时间:2024/04/29 03:07

有时,有些程序,需要具备自动更新功能;

对于程序代码量不大的二进制文件可以利用博文来进行存放再连接它来更新,这样可以解决网络稳定存放的问题,与更新问题,解决方案如下,当然这只能小量程序能用


1,创建一个博文;

2,把要更新的程序文件编码成base64文本,然后把这个文本放到博文内容中,

3.更新时程序读取博文的源代码,截取出这个base64再反编码成二进制程序文件即可完成;


这个方案有点小众,只是它有效嘀.因为东西不大话,找其它的存放地方,要不得密码,要不,无法直接下载,而文章却不一样


实例代码;




function upload() {
/*
 * 更新原理:连接到某篇博文,提取出博文中的版本号与当前的比较,如果线上比较新,就从博文中截取出代码替换即可完成更新支持存放代码到多个文章中
 * 首先下面的变量中指定首个文章地址,与当前的更新时间
 * 分隔符号使用#
 * 整个代码开始与结束使用10个#一篇文章只允许一对;
 * 时间使用3个#号,12位数字(年4位月2位日2位时2位分2位)二头各一个,如 ###201210111111###,且时间节只允许放在首个文章的整个代码开始节起始#号后面,即时间必须紧跟它,后面分数据不允许再放;
 * 余下部分数据文章url使用2个#号,因为文章有时一遍放不完全部代码,且它后面必须紧跟整个代码结束的截住标志,如 ##urlbase64后数据##
 * 文件数据节使用1个#号,前面一段是文件名base64后,后面一段是内容base64后数据,如 #dd33#dddjfjf#
 * 首个文章的中数据必须给出线上的数据的制作日期,以给线下的程序进行比较,是否需要更新,它的数据格式是如下:
 * 首个文章可能格式:注意不算空格,节与节连接之间可以使用\s来分隔,但是节二头的#与#号之间不允许有\s
 * ##### ###12位表示日期数字### #qvod.js base64后#内容base64后# ...如果有话,其它文件数据 ##如果有话,分部分文章url base64## #####
 * 分部文章中code可能格式,注意分部文章中是不允许有日期节.
 * ##### #qvod.js base64后#内容base64后# ...其它文件数据 ##如果有话分部分文章url base64## #####
 * 注释使用在注释二头放一个~号,注意注释内容不允许再包含~
 */
    var uploadInfo = {time:'201210251027', url:'http://hi.baidu.com/qidizi/item/8418f335f8d23781b611db01'};//版本更新信息
    _('uploadA').innerHTML = '<strong class="warn">正在检测升级数据中...请稍候</strong>';
    _('uploadA').disabled = true;
    var id = randomId();
    tip({html:'正在连接到远程页面(' + uploadInfo.url + ')检查是否有新更新,完成后会提示你进行下步操作,在这之前你可继续其它操作;<br /><a name="msajaxer">0</a>秒', id:id});
    var aText = '更新失败';
    var tipText = '更新失败';            
    var complete = function() {
        _('uploadA').disabled = false;
        _('uploadA').innerHTML = aText;
        tip({text:tipText});
    }
    
    _.msajax(uploadInfo.url,{
        success:function(html){
            html = html.match(/##########([\s\S]+)##########/);
            html = !html ? html : html[1].replace(/\s+|<[^<>]*>|~[^~]*~/g, '').match(/^###(\d{12,})###(?:##([^#]+)##)?(.+)$/);            
            
            if (html) {
                var time = html[1];                
                var part = html[2];
                var code = html[3];
                
                if (time > uploadInfo.time) {//有更新
                    if (/^\s*$/.test(code)) {
                        tipText = '首段数据无法解析,更新失败';
                    } else { 
                        var uploadDo = function() {
                            var oldDir = 'oldVer';
                            var fso = new ActiveXObject('Scripting.FileSystemObject');
                            var files = [];
                            fso.FolderExists(htaDir + oldDir) && fso.DeleteFolder(htaDir + oldDir, true);//移除上次更新前备份    
                            !fso.FolderExists(htaDir + oldDir) && fso.CreateFolder(htaDir + oldDir);//创建备份文件夹
                            fso.CopyFile(htaDir+ '*', htaDir+ oldDir, true);//备份文件

                            try {
                                code = code.replace(/#([^#]+)#([^#]+)#/g, function($0, $1, $2){
                                    $1 = base64decode($1);
                                    $2 = base64OrBin($2);
                                    
                                    if ('string' != typeof $2) {
                                        files[files.length] = {name:$1, data:$2};
                                    } else {
                                        return '文件' +$1+ '的数据校验失败,更新失败!';
                                    }
                                    
                                    return '';
                                });
                            } catch(e) {
                                tipText = '更新失败,解析文件代码出错:' + e.description;
                                complete();
                                return;
                            }
                            
                            if (!/^\s*$/.test(code) ) {
                                tipText = '更新文件数据格式错误,未能正确解析,更新失败!:' + code;
                            } else {
                                try {    
                                    for (var i = 0; i < files.length; i++) {
                                        bin2file(htaDir + files[i].name, files[i].data);
                                    }
                                    
                                    aText = '更新已应用(需刷新/重启)';
                                    tipText = '更新已经下载完成,并成功应用,刷新或是重启程序即可使用.';                            
                                } catch(e) {
                                    tipText = '更新失败,覆盖旧文件时出错,已经还原了旧文件:' + e.description;
                                    fso.CopyFile(htaDir+ oldDir + '/*', htaDir, true);//还原旧文件
                                }
                            }
                            
                            complete();
                        }
                        var nextPart = function() {
                            if (part) {
                                part = base64decode(part);
                                var parId = randomId();
                                tip({html:'正在尝试更新其它数据(' + part + '),请稍候...<br /><a name="msajaxer">0</a>秒', id:parId});

                                _.msajax(part,{
                                    success:function(partHtml){
                                        partHtml = partHtml.match(/##########([\s\S]+)##########/);
                                        partHtml = !partHtml ? partHtml : partHtml[1].replace(/\s+|<[^<>]*>|~[^~]*~/g, '').match(/^(?:##([^#]+)##)?(.+)$/);   
                                        
                                        if (partHtml) {
                                            var partCode = partHtml[2];
                                            
                                            if (/^\s*$/.test(partCode) ) {
                                                tipText = '后段数据丢失,无法解析,更新失败';
                                            } else {
                                                code += partCode;                                                
                                                part = partHtml[1];
                                                nextPart();
                                                return;
                                            }
                                        } else {
                                            tipText = '数据段' + part + '返回格式错误,无法解析,更新失败';
                                        }
                                        complete();
                                    }
                                    ,dataType: 'text'
                                    ,proxy:getProxy()
                                    ,error:function(data){
                                        aText = '检测异常,更新失败';
                                        tipText = '连接到更新页面' + part + '出错,请解决此问题后再尝试更新:' + data;
                                        complete();
                                    }
                                    ,type:'GET'
                                    ,complete:new Function('tip( {id:"' + parId + '", autoClose:0});')
                                });
                            } else {
                                uploadDo();
                            }
                        }
                        
                        nextPart();
                        return ;
                    }
                } else {
                    aText = '无需更新';
                    tipText = '更新检测成功,暂未有更新,请下次再尝试';
                }
            } else {
                tepText = '远程页面返回的数据无法解析,更新失败,可能是' +uploadInfo.url+ '页面变更后失效了'
            }
            
            complete();
        }
        ,dataType: 'text'
        ,proxy:getProxy()
        ,error:function(data){
            tipText = '无法连接远程页面' + uploadInfo.url + ',请解决此问题后再尝试更新:' + data;
            complete();
        }
        ,type:'GET'
        ,complete:new Function('tip( {id:"' + id + '", autoClose:0});')
    });
}

function base64Bar() {
    tip({html:'<form onsubmit="var els = this.elements;els[1].value = file2bin(els[0].value);return false;"><br/>选择文件<br/><input class="w100"  type=file /><br/>文件二进制base64转换后的字符<br/><input class="w100"/><br/><input type="submit" value="开始文件转化成base64字符" /></form>'
    +'<form onsubmit="var els = this.elements;bin2file(els[0].value, els[1].value);return false;"><br/>替换式保存文件<br/><input  class="w100" type="file" title="可以新建一文件再选择"/><br/>文件二进制base64后字符串<br/><input class="w100" /><input type="submit" value="开始base64储存到文件" /></form>'
    +'<form onsubmit="var els = this.elements;els[1].value = base64encode(els[0].value);return false;"><br/>待base64的字符<input    class="w100"/><br/>base64后字符<br/><input class="w100" /><bar/><input value="开始用base64加密" type="submit" /></form>'
    +'<form onsubmit="var els = this.elements;els[1].value = base64decode(els[0].value);return false;"><br/>待解的base64字符<input   class="w100"/><br/>解码后字符串<br/><input class="w100" /><br/><input type="submit" value="开始base64字符解密" /></form>'});
}

/*
 * bin必须是返回2进制的base64后的字符串
 */
function bin2file(path, bin, over) {
    if (!path) {
        alert('请指定路径');
        return false;
    }
    
    if ('' == bin || (null == bin) || (undefined == bin) ) {
        alert('bin2file数据必须指定');
        return false;
    }
    
    'string' == typeof bin && (bin = base64OrBin(bin));
    over = over ? over : 1;
    var fso = new ActiveXObject('Scripting.FileSystemObject');
    
    if (fso.FileExists(path) && !over) {
        alert('文件存在,不允许覆盖:' + path);
        return false;
    } 
    
    fso = null;
    var ado = new ActiveXObject('ADODB.Stream');
    var adSaveCreateOverwrite  = 2;
    var adTypeBinary = 1;
    ado.Open();
    ado.Type = adTypeBinary;
    ado.Position = 0;
    ado.Write(bin);
    ado.SaveToFile(path, adSaveCreateOverwrite);
    ado.Close();
    return true;
}

function base64OrBin(obj) {//设置base64,就输出bin,相反,设置bin就输出base64,会自动判别
    var xml = new ActiveXObject('Microsoft.XMLDOM');
    var node = xml.createElement("obj");
    node.dataType = "bin.base64";
    obj = 'string' == typeof obj ? (node.text = obj, node.nodeTypedValue) : (node.nodeTypedValue = obj, node.text);
    node = xml = null;
    return obj;
}

/*
 * 返回2进制的base64后的字符串
 */
function file2bin(path) {
    var fso = new ActiveXObject('Scripting.FileSystemObject');
    
    if (!fso.FileExists(path)) {
        alert('文件不存在:' + path);
        return null;
    }
    
    fso = null;
    var ado = new ActiveXObject('ADODB.Stream');
    var adReadAll  = -1;
    var adTypeBinary = 1;
    ado.Open();
    ado.Type = adTypeBinary;
    ado.LoadFromFile(path);
    ado.Position = 0;
    var bin = ado.Read(adReadAll);
    ado.Close();
    return base64OrBin(bin);
}