能否在Oracle OCI对象存储中在线解压ZIP文件?求示例代码
Oracle云对象存储在线解压ZIP文件方案
可行性确认
完全可行。你可以在Oracle云基础设施内直接完成ZIP文件的在线解压,无需将文件下载到本地再重新上传。核心方案是利用Oracle Functions无服务器函数,直接访问对象存储中的ZIP文件,在云侧计算环境内完成解压,再将解压后的文件直接写回对象存储,全程不经过本地机器,彻底节省大文件的上传下载时间。
Python + Oracle Functions 示例实现
前置要求
- 已完成Oracle Functions环境配置,函数需具备对象存储的读写权限(需配置动态组与IAM策略,例如允许函数
manage objects in compartment <你的 compartment名>) - 函数运行环境已预装
ociPython SDK与zipfile标准库
函数代码
import oci import zipfile from io import BytesIO import json def handler(ctx, data): # 解析输入参数:可通过函数调用时传入JSON格式参数 # 示例输入:{"source_bucket": "my-source-bucket", "source_object": "large-file.zip", "target_bucket": "my-target-bucket", "target_prefix": "unzipped/"} try: input_params = json.loads(data.decode('utf-8')) except: return {"status": "error", "message": "输入参数格式错误,需为JSON"} source_bucket = input_params.get("source_bucket") source_object = input_params.get("source_object") target_bucket = input_params.get("target_bucket", source_bucket) target_prefix = input_params.get("target_prefix", "") # 初始化对象存储客户端(使用资源主体认证) signer = oci.auth.signers.get_resource_principals_signer() object_storage_client = oci.object_storage.ObjectStorageClient(config={}, signer=signer) namespace = object_storage_client.get_namespace().data # 将ZIP文件读取到内存(不落地本地) get_obj_resp = object_storage_client.get_object(namespace, source_bucket, source_object) zip_stream = BytesIO(get_obj_resp.data.content) # 解压并批量上传文件 processed_count = 0 with zipfile.ZipFile(zip_stream, 'r') as zip_ref: for entry in zip_ref.infolist(): # 跳过目录条目 if entry.is_dir(): continue # 构造目标对象路径 target_obj_name = f"{target_prefix}{entry.filename}" # 读取解压后的文件内容 file_content = zip_ref.read(entry.filename) # 上传至目标存储桶 object_storage_client.put_object( namespace, target_bucket, target_obj_name, file_content ) processed_count += 1 return { "status": "success", "message": f"在线解压完成,共处理{processed_count}个文件" }
Java + Oracle Functions 示例实现
前置要求
- 已配置Oracle Functions Java运行环境,函数具备对象存储读写权限
- 项目依赖中包含OCI Java SDK与JSON解析库(如Jackson)
函数代码
import com.oracle.bmc.objectstorage.ObjectStorageClient; import com.oracle.bmc.objectstorage.requests.GetObjectRequest; import com.oracle.bmc.objectstorage.requests.PutObjectRequest; import com.oracle.bmc.objectstorage.responses.GetObjectResponse; import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class ZipUnzipFunction { public String handleRequest(byte[] inputBytes) { ObjectMapper mapper = new ObjectMapper(); JsonNode input; try { input = mapper.readTree(inputBytes); } catch (Exception e) { return "{\"status\":\"error\",\"message\":\"输入参数需为JSON格式\"}"; } String sourceBucket = input.get("source_bucket").asText(); String sourceObject = input.get("source_object").asText(); String targetBucket = input.has("target_bucket") ? input.get("target_bucket").asText() : sourceBucket; String targetPrefix = input.has("target_prefix") ? input.get("target_prefix").asText() : ""; // 初始化对象存储客户端 ResourcePrincipalAuthenticationDetailsProvider authProvider = ResourcePrincipalAuthenticationDetailsProvider.builder().build(); ObjectStorageClient osClient = ObjectStorageClient.builder().build(authProvider); String namespace = osClient.getNamespace(null).getValue(); int processedFiles = 0; try { // 获取ZIP文件流 GetObjectRequest getReq = GetObjectRequest.builder() .namespaceName(namespace) .bucketName(sourceBucket) .objectName(sourceObject) .build(); GetObjectResponse getResp = osClient.getObject(getReq); InputStream zipStream = getResp.getInputStream(); // 流式解压并上传 ZipInputStream zis = new ZipInputStream(zipStream); ZipEntry entry; byte[] buffer = new byte[4096]; while ((entry = zis.getNextEntry()) != null) { if (!entry.isDirectory()) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bytesRead; while ((bytesRead = zis.read(buffer)) != -1) { baos.write(buffer, 0, bytesRead); } byte[] fileContent = baos.toByteArray(); // 构造目标对象名 String targetObjName = targetPrefix + entry.getName(); // 上传至对象存储 PutObjectRequest putReq = PutObjectRequest.builder() .namespaceName(namespace) .bucketName(targetBucket) .objectName(targetObjName) .putObjectBody(new ByteArrayInputStream(fileContent)) .contentLength((long) fileContent.length) .build(); osClient.putObject(putReq); processedFiles++; } zis.closeEntry(); } zis.close(); return mapper.writeValueAsString( new Result("success", String.format("解压完成,共处理%d个文件", processedFiles)) ); } catch (Exception e) { try { return mapper.writeValueAsString( new Result("error", "解压失败:" + e.getMessage()) ); } catch (Exception ex) { return "{\"status\":\"error\",\"message\":\"处理失败且无法序列化错误信息\"}"; } } finally { osClient.close(); } } // 辅助类用于序列化结果 private static class Result { public String status; public String message; public Result(String status, String message) { this.status = status; this.message = message; } } }
关键注意事项
- 针对超大型ZIP文件(如几十GB级),建议采用流式分块处理,避免内存溢出;可调整函数的内存配置(如2GB以上)以适配大文件处理
- 确保函数的IAM权限足够:需允许
objectstorage:object:Get和objectstorage:object:Put操作 - 可配合对象存储的生命周期策略,自动清理原ZIP文件(若无需保留)
内容的提问来源于stack exchange,提问作者Techman007
相关产品推荐
相关产品推荐

