Unity3D资源打包AssetBundle云端动态加载-Python代码实现

效果
效果
测试使用版本Python3.4.3 七牛云存储。

使用流程:

1.在程序目录下创建对应平台的AssetBundle包管理文件夹。格式如:\com.smallsu.ar\android\
2.把打包好的BM.data和AssetBundle文件放进去
3.把creat_json.py放进去
4.执行creat_json.py(可以按住shift不放,右键空白处,在此处打开命令行窗口)
5.即可生成server.json


其中server.json的格式如下:
{
  "bundle_id": "com.CompanyName.ProductName",
  "bundle_version": "1.0.0",
  "control_manager": "BM.data",
  "control_scenes": [
    "默认场景名1",
    "默认场景名2",
    "默认场景名3"
  ],
  "control_tag": "该版本是用于XXX",
  "files": [
    {
      "md5": "f7e0b956540676a129760a3eae309294",
      "name": "BM.data",
      "size": 4,
      "time": "2016-03-22 14-29-02"
    },
    {
      "md5": "5321198845e603f173027e39bf0dc103",
      "name": "Book1.assetBundle",
      "size": 13,
      "time": "2016-03-22 14-29-02"
    },
    {
      "md5": "5321198845e603f173027e39bf0dc103",
      "name": "Book2.assetBundle",
      "size": 13,
      "time": "2016-03-22 14-29-02"
    },
    {
      "md5": "f7e0b956540676a129760a3eae309294",
      "name": "BM.data",
      "size": 4,
      "time": "2016-03-22 14-29-02"
    },
    {
      "md5": "5321198845e603f173027e39bf0dc103",
      "name": "Book1.assetBundle",
      "size": 13,
      "time": "2016-03-22 14-29-02"
    }
  ]
}

需要手动在server.json当中修改相关AssetBundle的信息。修改成功之后。使用uploadBundle.py把所有文件同步到七牛云即可。
Unity3D客户端直接http使用get请求。获取 https://七牛域名/com.smallsu.ar/android/server.json 即可读取相关信息。

环境配置方法:
安装python3.4.3 install.msi
执行pip命令
pip install qiniu
pip install require

相关代码:

# uploadBundle.py

import os
import sys
from easy_qiniu import SevenCow

#可获取文件夹内全部文件名(包括子文件夹)
def get_all_files(DirectoryPath):
    filenamesList = []
    for dirpath, dirnames, filenames in os.walk(DirectoryPath):
        """
        dirpath:当前遍历文件夹全名
        dirnames:当前文件夹内子文件夹名
        filenames:当前文件夹下文件名列表(不包括子文件夹里的文件)
        """
        for filename in filenames:
            filenamesList.append(dirpath + '/' + filename)#全名
    return filenamesList

#生成网站根目录形式的文件名
def get_root_filename(fullname):
    dir_path = sys.path[0]
    return fullname[len(sys.path[0]) + 1:len(fullname)].replace('\\','/')

#生成{目标文件名:源文件名,...}形式的字典
def get_filenames_dict(filenamesList=[]):
    filenames_dict = {}
    for filename in filenamesList:
        filenames_dict[get_root_filename(filename)] = filename
    return filenames_dict

#上传,根据返回值判断是否成功
def upload_into_qiniu(access_key,secret_key,bucket_name,director_path=sys.path[0]):
    try:
        sc = SevenCow(access_key,secret_key)
        sc.delete_files(bucket_name,sc.list_file_names(bucket_name)[0])
        sc.upload_files(bucket_name,get_filenames_dict(get_all_files(director_path)))
    except:
        return False
    else:
        return True

access_key = '七牛密匙'
secret_key = '七牛密匙'
bucket_name = '七牛空间名'

if(upload_into_qiniu(access_key,secret_key,bucket_name,director_path=sys.path[0])):
    print('Bak Successful')
else:
    print('Bak Error')

#creat_json.py

#-*-encoding:utf-8-*-
import os,sys
import hashlib
import datetime
import json

#可获取文件夹内全部文件名(包括子文件夹)
def get_all_files(DirectoryPath):
    filenamesList = []
    for dirpath, dirnames, filenames in os.walk(DirectoryPath):
        """
        dirpath:当前遍历文件夹全名
        dirnames:当前文件夹内子文件夹名
        filenames:当前文件夹下文件名列表(不包括子文件夹里的文件)
        """
        for filename in filenames:
            filenamesList.append(dirpath + '/' + filename)#全名
    return filenamesList

# 计算文件的MD5值
def md5_file(name):
    m = hashlib.md5()
    a_file = open(name, 'rb')    #需要使用二进制格式读取文件内容
    m.update(a_file.read())
    a_file.close()
    return m.hexdigest()

# 保存文件到本地
def save(filename, contents):
  fh = open(filename, 'w')
  fh.write(contents)
  fh.close()

# 主函数
if __name__ == "__main__":
    # 获取列表信息
    pathList = get_all_files(sys.path[0])

    server={}
    server["bundle_id"]="com.CompanyName.ProductName"
    server["bundle_version"]="1.0.0"

    server["control_manager"]="BM.data"
    server["control_scenes"]=[]
    server["control_scenes"].append("默认场景名1")
    server["control_scenes"].append("默认场景名2")
    server["control_scenes"].append("默认场景名3")

    server["control_tag"]="该版本是用于XXX"

    server["files"]=[]

    for path in pathList:
        if(os.path.splitext(path)[1] in [".data",".assetBundle"]):
            file={}
            file["name"]=os.path.basename(path)
            file["md5"]=md5_file(path)
            file["size"]=os.path.getsize(path)
            file["time"]=datetime.datetime.fromtimestamp(os.path.getmtime(path)).strftime("%Y-%m-%d %H-%M-%S")
            server["files"].append(file)

    res = json.dumps(server, sort_keys=True, indent=2, ensure_ascii=False)

    print(res)
    save('server.json',res)

#easy_qiniu.py

from qiniu import  Auth
from qiniu import put_file
from qiniu import BucketManager
from qiniu import build_batch_stat
from qiniu import build_batch_copy
from qiniu import build_batch_move
from qiniu import build_batch_delete
from qiniu import etag

import requests
import mimetypes

#class SevenCowException(Exception):
#    def __init__(self,status_code,content):
#        self.url = url
#        self.status_code = status_code
#        self.content = content
#        Exception.__init__(self, content)

class SevenCow(object):
    def __init__(self, access_key,secret_key):
        self.__access_key = access_key
        self.__secret_key = secret_key
        #使用access_key,secret_key登陆七牛,得到Auth类型返回值,以它作为后续操作凭证
        self.__auth = Auth(access_key, secret_key)

        

    # 上传本地文件(断点续上传、分块并行上传)
    def upload_files(self,bucket_name='',filedict={},
                     mime_type='',params={'x:a': 'a'}):
        """Args:
        bucket_name:'bucket_name'
        filedict: {'key':'localfile',...}
        mime_type: mime_type
        params: eg {'x:var': 'var'} 
        """

        """
        params用法:
        params={'x:price':'price','x:location':'location'}

        html文件中:
            <form method="post" action="http://upload.qiniu.com/" enctype="multipart/form-data">
                <input name="key" type="hidden" value="sunflower.jpg">
                <input name="x:location" type="hidden" value="Shanghai">
                <input name="x:price" type="hidden" value="1500.00">
                <input name="token" type="hidden" value="...">
                <input name="file" type="file" />
            </form>

        之后用户点击input按钮后,传给http://upload.qiniu.com的请求报文就会变成:

            name=sunflower.jpg&hash=Fn6qeQi4VDLQ347NiRm- \
            RlQx_4O2&location=Shanghai&price=1500.00

        然后七牛接受到后会将此作为回调请求的Body调用callbackUrl指定的回调服务器。
        """
        # 上传本地文件(断点续上传、分块并行上传)
        rets = []
        infos = []
        for key in filedict.keys():
            #上传策略仅指定空间名和上传后的文件名,其他参数为默认值
            token = self.__auth.upload_token(bucket_name, key)
            progress_handler = lambda progress, total: progress
            if(mime_type == ''):
                ret,info = put_file(token, key, filedict[key], params ,mime_type=mimetypes.guess_type(key)[0], progress_handler=progress_handler)
            else:
                ret,info = put_file(token, key, filedict[key], params ,mime_type=mime_type, progress_handler=progress_handler)
            #assert ret['key'] == key
            rets.append(ret)
            infos.append(info)
        return rets,infos

    def download_files(self,url='',filedict={}):
        """Args:
        url: 'url'
        filedict: {'key':'localfile',...}
        """
        if(url[0:4].upper() != 'HTTP'):
            url = 'http://' + url
        status_codes = []
        for fkey in filedict.keys():
            with open(filedict[fkey], "wb") as file:
                r = requests.get(url + '/' + fkey,timeout=5)
                status_codes.append(r.status_code)
                file.write(r.content)
        return status_codes

    # 获取文件信息
    def get_file_info(self,bucket_name,keys=[]):
        """Args:
        bucket_name:'bucket_name'
        keys:  ['fileName1','fileName2']
        """
        bucket = BucketManager(self.__auth)
        ops = build_batch_stat(bucket_name, keys)
        ret, info = bucket.batch(ops)
        return ret,info

    # 复制文件
    def copy_files(self,source_bucket,target_bucket,pathdict={}):
        """Args:
        source_bucket: 'source_bucket'
        target_bucket:  'target_bucket'
        pathdict: {'source_file_name':'target_file_name',...}
        """
        bucket = BucketManager(self.__auth)
        ops = build_batch_copy(source_bucket, pathdict, target_bucket)
        ret, info = bucket.batch(ops)
        return ret,info

    # 移动文件
    def move_files(self,source_bucket,target_bucket,pathdict={}):
        """Args:
        source_bucket: 'source_bucket'
        target_bucket:  'target_bucket'
        pathdict: {'source_file_name':'target_file_name',...}
        """
        bucket = BucketManager(self.__auth)
        ops = build_batch_move(source_bucket, pathdict, target_bucket)
        ret, info = bucket.batch(ops)
        return ret,info

    # 删除文件
    def delete_files(self,source_bucket,pathlist=[]):
        """Args:
        source_bucket: 'source_bucket'
        pathlist: ['source_file_name',...]
        """
        bucket = BucketManager(self.__auth)
        ops = build_batch_delete(source_bucket, pathlist)
        ret, info = bucket.batch(ops)
        return ret,info

    # 列出所有文件
    def list_file_names(self,bucket_name, prefix=None, marker=None, limit=None, delimiter=None):
        """
        Args:
            bucket:     空间名
            prefix:     列举前缀
            marker:     列举标识符(首次为None)
            limit:      单次列举个数限制(默认列举全部)
            delimiter:  指定目录分隔符
            
        Returns:
            pathlist: ['file_name',...]
        """
        file_name_list = []
        bucket = BucketManager(self.__auth)
        marker = None
        eof = False
        while eof is False:
            ret, eof, info = bucket.list(bucket_name, prefix=prefix, marker=marker, limit=limit)
            marker = ret.get('marker', None)
            for item in ret['items']:
                file_name_list.append(item['key'])
        return file_name_list,eof

    # 抓取资源
    def fetch_files_from_net_to_qiniu(self,bucket_name,pathdict={}):
        """Args:
        bucket_name: 'bucket_name'
        pathdict: {'source_file_name':'target_file_name',...}
        """
        bucket = BucketManager(self.__auth)
        rets=[]
        infos=[]
        for p in pathdict.keys():
            ret, info = bucket.fetch(pathdict[p], bucket_name,p)
            rets.append(ret)
            infos.append(info)
        return rets,infos

    # 更新镜像资源
    def update_image_source(self,bucket_name,pathlist=[]):
        """Args:
        bucket_name: 'bucket_name'
        pathlist: ['file_name',...]
        !需要提前对仓库设置镜像源!
        """

        bucket = BucketManager(self.__auth)
        rets=[]
        infos=[]
        for p in pathlist:
            ret, info = bucket.prefetch(bucket_name, p)
            rets.append(ret)
            infos.append(info)
        return rets,infos
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容