`

更新服务器文件到本地2

阅读更多
功能要求:
    通过Http协议,向服务器发送请求,得到返回的json格式数据,根据返回的文件路径和MD5值,判断本地对应目录的文件是否和服务器上的文件一致,不一致则更新。


#!/usr/bin/python
#-*- coding: utf-8 -*-
'''
    功能描述:用于同步服务器的配置文件
'''
import urllib2
import os
import json
import hashlib
import thread
import time
import urllib
from time import sleep
import threading
from tools import getLogger
from tools import DIRS
import logging
import re

LOG_NAME='syncservicefile'

log =getLogger(LOG_NAME)

#服务请求根路径
SERVICE_ADDRESS='http://132.121.130.21:5000/sync/'

#文件名称过滤表达式(Python正则表达式),暂时先过滤掉以.pyc结尾的文件
FILTER_FILENAME_REG=r'.*?\.pyc$'

#生成本地的MD5文件,用于比对服务器上的MD5文件
def sendRequest():
    serviceDict={}   #存放服务器上的文件名,字典值
    tempList=[]      #存放临时文件
    log.info('send request to service............')
    jsonStr = urllib2.urlopen(SERVICE_ADDRESS).read()
    if len(jsonStr) < 3:
        log.info('没有需要同步的文件,请检查item表的配置是否正确..........')
    else:
       
        #读取本地目录
        dirDict=readFileDir()
        reObj=re.compile(FILTER_FILENAME_REG)
        jsoObj = json.loads(jsonStr)
        for path in jsoObj.keys():
            #过滤匹配的文件路径
            if not reObj.match(path):
                #获取服务器返回的文件路径和文件的md5值
                filepath = path
                md5= jsoObj[path]['md5']
                mtime = jsoObj[path]['mtime']  #时间比对暂时没用
                #将 filepath 与 字典值中的key进行比对,如果有则说明本地文件已存在,否则本地文件不存在
                if dirDict.has_key('/'+filepath):
                    #说明本地已存在该文件,比较本地文件的MD5值
                    newmd5=MD5(dirDict['/'+filepath])
                    if md5==newmd5:
                        pass
                    else:
                        #下载文件到本地,同时将文件路径保存在集合中
                        dowloadFile(filepath,dirDict['/'+filepath])
                else:
                    #说明该文件在本地不存在
                    for j in DIRS.keys():
                        key = j
                        cpath = DIRS[j]
                        firstDirName = filepath.split('/')[0]
                        array = cpath.split('/')
                        length = len(array)
                        lastDirName = array[length-2]
                        if firstDirName == lastDirName:
                            #说明目录匹配成功
                            locapath= cpath + filepath[filepath.find('/')+1:len(filepath)]
                            #判断本地文件夹是否存在,不存在则新建
                            dirpath=os.path.dirname(locapath)
                            if not os.path.exists(dirpath):
                                os.makedirs(dirpath)
                            #下载文件到本地目录
                            dowloadFile(filepath,locapath,tempList)
                           
                #保存服务器上文件字典值
                serviceDict[filepath] = md5
               
                time.sleep(1)
                       
        compFileMd5(serviceDict,dirDict)
       
      
'''
将文件下载到本地目录中,先保存为以.temp结尾的文件
filepath:远程文件路径
locapath:本地文件路径
tempList:存放本地临时文件路径
'''              
def dowloadFile(filepath,locapath,tempList=None):
    #将临时文件目录保存在集合中,用于下载完直接修改文件后缀名
    tempath = locapath + '.tmp'
    tempList.append(tempath)
    log.info(filepath + '--->' + locapath+'.tmp')
    urllib.urlretrieve(os.path.join(SERVICE_ADDRESS,filepath),tempath)

'''
获取文件的md5值
filepath:文件的路径
'''
def MD5(filepath):
    with open(filepath,'rb') as f:
        md5obj = hashlib.md5()
        md5obj.update(f.read())
        hash = md5obj.hexdigest()
        return hash

#读取本地文件目录,返回文件字典
def readFileDir():
    dirDict={}
    for dir in DIRS.values():
        gci(dir,dir,dirDict)

    return dirDict

#递归遍历文件目录
'''
将文件路径 和   完全路径分别作为key,value保存在字典中
dirpath:文件目录
keydir:主目录 即tools中的DIRS变量中的key
dirDict:返回字典值
'''  
def gci(dirpath,keydir,dirDict):
    files = os.listdir(dirpath)
    for fi in files:
        fi_d = os.path.join(dirpath,fi)
        if os.path.isdir(fi_d):
            gci(fi_d,keydir)
        else:
            dirDict[fi_d.split('..')[1]]=fi_d
    return dirDict


'''
比较下载文件的临时文件的md5值,如果跟服务器上文件的md5值一致,在重命名,否则提示下载失败
dirDict:本地的文件字典
serviceDict:服务器上的文件字典
'''

def compFileMd5(serviceDict,dirDict):
    #这里需要重新遍历一下本地路径
    dirDict=readFileDir()
   
    for key1 in serviceDict.keys():
        serviceKey = key1
        serviceMd5 = serviceDict[key1]
        temp1 = '/' + serviceKey + '.tmp'
        temLocalPath = dirDict[temp1]
        localPath = temLocalPath[0:len(temLocalPath)-4]
        if os.path.exists(temLocalPath):
            #比较临时文件的MD5值是否和服务器一致
            localMd5 = MD5(temLocalPath)
            if localMd5 == serviceMd5:
                rename(temLocalPath,localPath)
            else:
                log.error('Error downloading file of' + serviceKey)
               
    

'''
将文件重命名
oldpath:旧的文件路径
newpath:新的文件路径
'''
def rename(oldpath, newpath):
    try:
        os.rename(oldpath, newpath)
        log.info('rename: ' + oldpath + '---->' + newpath)
    except Exception,e:
        log.error('修改文件名称出错..........')
        log.error('rename file has error.......' + oldpath)
       

if __name__ == '__main__':
    log.info(time.strftime('%Y-%m-%d %H:%M:%S'))
    log.info('.............开始同步服务器文件.............')
   
    sendRequest()
   
    log.info(time.strftime('%Y-%m-%d %H:%M:%S'))
    log.info('.............同步服务器文件结束.............')
   
  
   


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics