You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在Oracle OCI对象存储中在线解压ZIP文件?求示例代码

Oracle云对象存储在线解压ZIP文件方案

可行性确认

完全可行。你可以在Oracle云基础设施内直接完成ZIP文件的在线解压,无需将文件下载到本地再重新上传。核心方案是利用Oracle Functions无服务器函数,直接访问对象存储中的ZIP文件,在云侧计算环境内完成解压,再将解压后的文件直接写回对象存储,全程不经过本地机器,彻底节省大文件的上传下载时间。

Python + Oracle Functions 示例实现

前置要求

  • 已完成Oracle Functions环境配置,函数需具备对象存储的读写权限(需配置动态组与IAM策略,例如允许函数manage objects in compartment <你的 compartment名>)
  • 函数运行环境已预装oci Python 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 15:55:16