使用函数计算实现自动解压上传到OSS的ZIP文件
目前对象存储不支持解压上传的ZIP的文件,您可以通过使用函数计算服务来配合实现。当匹配解压规则的ZIP文件上传到对象存储后,会自动触发函数计算进行解压。文件解压完成后,会存储至对象存储的指定目录中。
注意事项
建议使用UTF-8或GB 2312编码命名您的文件或文件夹,否则可能会出现解压后的文件或文件夹名称出现乱码、解压过程中断等问题。
归档或冷归档类型的文件需先解冻再解压。
解压单个压缩包的最大时间是2小时,超过2小时未完成的任务会解压失败。
建议ZIP包里面的单文件大小最好不超过1 GB,否则可能解压失败。
建议设置函数的执行时长为2小时以上,最大可到24小时。
前提条件
操作流程
步骤一:创建函数
登录函数计算控制台,在左侧导航栏,单击函数。
在顶部菜单栏,选择地域,然后在函数页面,单击创建函数。
在创建函数页面,按需选择创建函数的方式,配置以下配置项,然后单击创建。
重要配置项说明,如下所示,其余配置项的设置请参见创建函数。
运行环境:选择为Python 3.10。
函数角色:选择已有角色或创建角色,请确保函数拥有访问OSS Bucket的权限,您可以为该角色授予AliyunOSSFullAccess权限策略。
在函数详情页面,选择代码页签,在代码编辑器中编写代码,然后单击部署代码。
涉及的代码示例如下。以下示例仅为index.py代码示例,代码中需要导入的helper包和zipfile包,请参见start-unzip-oss-v3,对应的代码名称分别为
helper.py
和ossZipfile.py
。说明当前示例代码支持一键部署,您可以直接在函数计算FC中一键部署本代码。start-unzip-oss-v3
# -*- coding: utf-8 -*- ''' 声明: 这个函数针对文件和文件夹命名编码是如下格式: 1. mac/linux 系统, 默认是utf-8 2. windows 系统, 默认是gb2312, 也可以是utf-8 对于其他编码,我们这里尝试使用chardet这个库进行编码判断,但是这个并不能保证100% 正确, 建议用户先调试函数,如果有必要再改写函数,并保证调试通过。 Statement: This function names and encodes files and folders as follows: 1. MAC/Linux system, default is utf-8 2. For Windows, the default is gb2312 or utf-8 For other encodings, we try to use the chardet library for coding judgment here, but this is not guaranteed to be 100% correct. If necessary to rewrite this function, and ensure that the debugging pass ''' import helper import oss2 import json import os import time import logging import chardet """ When a source/ prefix object is placed in an OSS, it is hoped that the object will be decompressed and then stored in the OSS as processed/ prefixed. For example, source/a.zip will be processed as processed/a/... "Source /", "processed/" can be changed according to the user's requirements. """ # Close the info log printed by the oss SDK logging.getLogger("oss2.api").setLevel(logging.ERROR) logging.getLogger("oss2.auth").setLevel(logging.ERROR) LOGGER = logging.getLogger() # a decorator for print the excute time of a function def print_excute_time(func): def wrapper(*args, **kwargs): local_time = time.time() ret = func(*args, **kwargs) LOGGER.info('current Function [%s] excute time is %.2f' % (func.__name__, time.time() - local_time)) return ret return wrapper def get_zipfile_name(origin_name): # 解决中文乱码问题 name = origin_name try: name_bytes = origin_name.encode(encoding="cp437") except: name_bytes = origin_name.encode(encoding="utf-8") # the string to be detect is long enough, the detection result accuracy is higher detect = chardet.detect(name_bytes) confidence = detect["confidence"] detect_encoding = detect["encoding"] if confidence > 0.75 and (detect_encoding.lower() in ["gb2312", "gbk", "gb18030", "ascii", "utf-8"]): try: if detect_encoding.lower() in ["gb2312", "gbk", "gb18030"]: detect_encoding = "gb18030" name = name_bytes.decode(detect_encoding) except: name = name_bytes.decode(encoding="gb18030") else: try: name = name_bytes.decode(encoding="gb18030") except: name = name_bytes.decode(encoding="utf-8") # fix windows \\ as dir segment name = name.replace("\\", "/") return name @print_excute_time def handler(event, context): """ The object from OSS will be decompressed automatically . param: event: The OSS event json string. Including oss object uri and other information. For detail info, please refer https://help.aliyun.com/document_detail/70140.html?spm=a2c4g.11186623.6.578.5eb8cc74AJCA9p#OSS param: context: The function context, including credential and runtime info. For detail info, please refer to https://help.aliyun.com/document_detail/56316.html#using-context """ evt_lst = json.loads(event) creds = context.credentials auth = oss2.StsAuth( creds.access_key_id, creds.access_key_secret, creds.security_token) evt = evt_lst['events'][0] bucket_name = evt['oss']['bucket']['name'] endpoint = 'oss-' + evt['region'] + '-internal.aliyuncs.com' bucket = oss2.Bucket(auth, endpoint, bucket_name) object_name = evt['oss']['object']['key'] if "ObjectCreated:PutSymlink" == evt['eventName']: object_name = bucket.get_symlink(object_name).target_key if object_name == "": raise RuntimeError('{} is invalid symlink file'.format( evt['oss']['object']['key'])) file_type = os.path.splitext(object_name)[1] if file_type != ".zip": raise RuntimeError('{} filetype is not zip'.format(object_name)) LOGGER.info("start to decompress zip file = {}".format(object_name)) lst = object_name.split("/") zip_name = lst[-1] PROCESSED_DIR = os.environ.get("PROCESSED_DIR", "") RETAIN_FILE_NAME = os.environ.get("RETAIN_FILE_NAME", "") if PROCESSED_DIR and PROCESSED_DIR[-1] != "/": PROCESSED_DIR += "/" if RETAIN_FILE_NAME == "false": newKey = PROCESSED_DIR else: newKey = PROCESSED_DIR + zip_name zip_fp = helper.OssStreamFileLikeObject(bucket, object_name) newKey = newKey.replace(".zip", "/") with helper.zipfile_support_oss.ZipFile(zip_fp) as zip_file: for name in zip_file.namelist(): with zip_file.open(name) as file_obj: name = get_zipfile_name(name) bucket.put_object(newKey + name, file_obj)
步骤二:创建OSS触发器
在函数详情页面,选择配置页签,然后在左侧导航栏,选择触发器页签。
在触发器页面,单击创建触发器,在创建触发器面板,按需设置配置项,然后单击确定。
重要配置项说明如下,其余配置项的说明请参见配置原生OSS触发器。
触发器类型选择对象存储OSS。
Bucket 名称选择已创建的存储空间名称。
设置文件前缀,本文示例为
src
。设置文件后缀,本文示例为
zip
。选择触发事件,本文示例为
oss:ObjectCreated:PutObject, oss:ObjectCreated:PostObject, oss:ObjectCreated:CompleteMultipartUpload, oss:ObjectCreated:PutSymlink
。角色名称:选择角色名称,请确保该角色拥有调用函数的权限,您可以为该角色授予AliyunFCFullAccess权限策略。
创建完成后,您可以在触发器页面查看已创建的OSS触发器。
步骤三:测试验证
您可以通过以下两种方式测试验证结果。
方式一:通过控制台手动上传文件验证
登录对象存储控制台,在步骤二:创建OSS触发器时选择的Bucket的src
目录下上传ZIP文件,例如code.zip
。上传成功后,将自动触发函数执行,解压ZIP文件并将解压后的文件转存到目标目录dst/
。目标目录为自动创建,您无需手动创建。
方式二:通过配置触发器的event参数测试验证
event参数配置完成后,您需要手动单击测试函数触发函数执行,然后登录对象存储控制台,查看目标Bucket的文件列表,如果已解压目标ZIP文件,并将解压后的文件转存到目标路径dst/
表示测试成功。具体操作步骤如下。
在函数详情页面,单击代码页签,然后单击测试函数右侧图标,从下拉列表中,选择配置测试参数。
在配置测试参数面板,选择事件模板,填写事件名称和event内容,然后单击确定。
event示例如下。
{ "events": [ { "eventName": "ObjectCreated:PutObject", "eventSource": "acs:oss", "eventTime": "2023-08-13T06:45:43.000Z", "eventVersion": "1.0", "oss": { "bucket": { "arn": "acs:oss:cn-hangzhou:10343546824****:bucket****", "name": "bucket****", "ownerIdentity": "10343546824****" }, "object": { "deltaSize": 122539, "eTag": "688A7BF4F233DC9C88A80BF985AB****", "key": "src/test.zip", "size": 122539 }, "ossSchemaVersion": "1.0", "ruleId": "9adac8e253828f4f7c0466d941fa3db81161****" }, "region": "cn-hangzhou", "requestParameters": { "sourceIPAddress": "140.205.XX.XX" }, "responseElements": { "requestId": "58F9FF2D3DF792092E12044C" }, "userIdentity": { "principalId": "10343546824****" } } ] }
event参数中不同属性字段的解释,请参见配置函数入口参数。
重要以上event内容仅为示例,请根据实际信息修改部分参数,同时,确保配置的Bucket中存在指定的文件(本文示例为
src/test.zip
文件),否则无法触发函数执行,或者函数执行会失败。需要根据实际情况修改的参数如下所示:
bucket.arn
:示例如acs:oss:<region>:<your_account_id>:<your_bucket>
,修改<region>
为您创建函数时选择的地域,修改<your_account_id>
为您的阿里云账号(主账号)ID,修改<your_bucket>
为相同地域下您实际已经创建的Bucket名称。您的阿里云账号ID,可在函数计算控制台的概览页面的常用信息区域获取。bucket.name
:修改为相同地域下您实际已经创建的Bucket名称。bucket.ownerIdentity
:修改为您的阿里云账号ID。object.key
:修改为您实际已经上传到目标Bucket下的文件。region
:修改为您创建函数时选择的地域。userIdentity.principalId
:修改为您的阿里云账号ID。
单击代码页签的测试函数进行测试。
执行成功后,登录对象存储控制台,查看目标Bucket下目标ZIP文件(本文示例为
src/test.zip
)是否已被解压并保存至dst/
目录。具体操作,请参见通过OSS控制台查询文件。
测试完成后,如果您暂时不需要使用此应用,请及时删除应用以及关联的其他资源。
相关文档
如果需要使用OSS触发器实现更多功能,请参见OSS触发器概述。
如果需要使用函数计算实现打包下载OSS的文件,请参见使用函数计算打包下载OSS文件。
如果需要了解本文中提到的对象存储相关的操作,请参见存储空间(Bucket)和对象/文件(Object)。
- 本页导读 (1)