上传云对象存储代码实践-华为云OBS

系列文章目录

第一章 上传到华为云OBS



前言

FTP、HTTP作为文件存储服务器越来越无法满足当今对数据存储,下载,安全的要求,对象存储服务器成文主流。

当前主流云端对象存储服务

AWS S3 (Simple Storage Service)
作为行业先驱,AWS S3 提供高扩展性、99.999999999% 数据持久性,支持跨区域复制和细粒度权限控制。其与 AWS 生态的无缝集成(如 Lambda、Redshift)使其成为企业多云策略的核心组件。

Google Cloud Storage
凭借全球骨干网和低价冷存储(如 Archive 类),GCS 在数据分析场景(BigQuery、TensorFlow)中表现突出。其统一存储层设计简化了数据生命周期管理。

Azure Blob Storage
深度集成 Microsoft 365 和 Active Directory,提供行业合规认证(HIPAA、GDPR)。热/冷/归档分层存储结合低延迟 CDN 加速,适合混合云部署场景。

阿里云 OSS (Object Storage Service)
在中国及东南亚市场占据主导地位,提供抗 DDoS 能力和图片处理 API。其跨区域容灾方案满足金融级合规要求,价格策略极具地域竞争力。

华为云 OBS (Object Storage Service)
突出数据加密和芯片级安全,适合政府项目。与 Kunpeng 处理器协同优化,在 AI 训练等高吞吐场景中表现优异。

流行技术驱动因素

无状态架构适配
RESTful API 设计天然契合微服务通信模式,预签名 URL 等特性简化了前后端分离架构下的文件交互逻辑。

成本弹性优势
按需付费模型消除前期硬件投入,存储分层(如 S3 Intelligent-Tiering)可自动优化冷热数据成本,相比传统 NAS 节省 50% 以上 TCO。

数据分析融合
与 Spark、Presto 等引擎的深度集成(如 S3 Select、GCS Connector)实现了存算分离架构,避免了 ETL 过程中的数据搬迁开销。

边缘计算协同
Cloudflare R2、Backblaze B2 等新兴服务通过零出口费用策略,与边缘节点(如 AWS Lambda@Edge)组合构建低延迟内容分发网络。

合规性自动化
内置版本控制、WORM(一次写入多次读取)和审计日志功能,满足金融、医疗等行业对数据不可篡改性的刚性需求。


一、华为云OBS

华为云OBS简介

华为云对象存储服务(Object Storage Service,OBS)是一种高可靠、高可用、高性能的云存储服务,适用于海量数据存储、备份、归档、大数据分析等场景。OBS提供两种核心存储类型:存储桶(Bucket)并行文件系统(Parallel File System),满足不同业务需求。


存储桶(Bucket)

存储桶是OBS中存储对象(Object)的基本容器,所有对象必须属于某个存储桶。存储桶提供标准的对象存储功能,适用于通用文件存储、静态网站托管、数据备份等场景。

核心特性

  • 扁平化存储结构:无目录层级,通过前缀(如folder1/file.txt)模拟目录结构。
  • 高扩展性:支持无限容量,单个对象最大支持48.8TB。
  • 多存储类型:支持标准、低频访问、归档存储,平衡成本与访问性能。
  • 数据安全:支持服务端加密(SSE)、防盗链、跨区域复制(CRR)等功能。

典型应用场景

  • 静态网站托管:直接通过OBS托管HTML/CSS/JS文件。
  • 大数据分析:与华为云MapReduce、DLI等服务集成,存储原始数据。
  • 备份归档:通过生命周期规则自动转储至低频或归档存储。

并行文件系统(Parallel File System)

并行文件系统是OBS提供的高性能文件存储服务,兼容POSIX文件系统语义,适用于需要高吞吐、低延迟的场景,如高性能计算(HPC)、AI训练等。

核心特性

  • 高性能访问:支持多客户端并发读写,吞吐量可达GB/s级别。
  • POSIX兼容:支持文件锁、原子操作等标准文件系统特性。
  • 与OBS互通:底层基于OBS存储桶,数据可通过OBS API直接访问。

典型应用场景

  • AI训练:加速模型训练中大规模数据集的读取。
  • 媒体处理:支持4K/8K视频编辑等高带宽需求场景。
  • 科学计算:为气象分析、基因测序等提供高吞吐存储支持。

存储桶与并行文件系统对比

特性存储桶并行文件系统
存储模型扁平化对象存储层次化文件系统(POSIX兼容)
访问协议RESTful API、SDK、S3兼容接口POSIX文件接口(如NFS、HDFS)
性能适合高并发小文件适合大文件高吞吐场景
适用场景通用存储、备份归档HPC、AI训练、实时数据分析

选择建议

  • 需兼容传统文件系统或高性能计算时,选择并行文件系统。
  • 需要低成本存储或简单对象管理时,使用存储桶。

华为云OBS支持两种存储类型灵活组合,用户可根据业务需求选择或混合使用。

二、使用步骤和代码实践

1. OBS上建立存储桶,AK、SK

登录华为云,找到OBS入口

  • 创建桶
    创建桶

2.上传代码实现-JAVA

  • 获取文件流、文件大小,若文件大于5G,分段上传
long singleMaxFileSize = 5*1024*1024*1024L;//5GB
String filePath = "D:/test.zip";
InputStream inputStream = new FileInputStream(filePath);
File file = new File(filePath);
long fileSize = file.length;
String cloudUrl = "";
if(fileSize < singleMaxFileSize)
{
    cloudUrl = obsUtil.uploadFile(filePath, inputStream, fileSize);
}
else
{
    cloudUrl = obsUtil.uploadBigFile(filePath, inputStream, fileSize);
}
  • obsUtil.uploadFile()实现细节,getBucketName是存储桶名字
  • obsClient可以通过ObsClient obsClient = new ObsClient(ak, sk,endPoint);endPoint是存储桶所在地域
  • redisTemplate是redis接口类,用于前端回调
  • getFilePathInObs是构建OBS下载链接
public String uploadFileToOss(String path, InputStream inputStream, long fileSize) {
        if (null == inputStream) {
            return null;
        }
        // 文件上传
        PutObjectRequest request = new PutObjectRequest(getBucketName(), path);
        request.setInput(inputStream);

        ObjectMetadata objectMetadata = new ObjectMetadata();
        // 流式上传,此时必须设置对象属性中的对象长度(Content-Length)
        // 不然ProgressStatus.getTransferPercentage()只会返回-1
        objectMetadata.setContentLength(fileSize);
        request.setMetadata(objectMetadata);

        final String objectKey = path;
        request.setProgressListener(
                new ProgressListener() {
                    @Override
                    public void progressChanged(ProgressStatus status) {

                        com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
                        jsonObject.put("getInstantaneousSpeed", status.getInstantaneousSpeed()/(1024.0 * 1024.0) + "MB/s");//上传瞬时速率
                        jsonObject.put("getAverageSpeed", status.getAverageSpeed()/(1024.0 * 1024.0) + "MB/s");//上传平均速率
                        jsonObject.put("getTransferPercentage", status.getTransferPercentage()+"%");//上传进度百分比

                        long timeout = 1;
                        redisTemplate.opsForValue().set("process:"+objectKey, jsonObject.toJSONString(), timeout, TimeUnit.DAYS);
                    }
                });
        // 每上传1MB数据反馈上传进度
        request.setProgressInterval(1024 * 1024L);
        obsClient.putObject(request);

        return getFilePathInObs(path);
    }
  • obsUtil.uploadBigFile()实现细节
public String uploadBigFileToOss(String path, InputStream inputStream, long fileSize) {
        if (null == inputStream) {
            return null;
        }

        final String bucketName = getBucketName();
        final String objectKey = path;
        // 初始化线程池
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        //final File largeFile = new File("localfile");
        // 初始化分段上传任务
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectKey);
        InitiateMultipartUploadResult result = super.initiateMultipartUpload(request);
        final String uploadId = result.getUploadId();
        // 每段上传100MB
        long partSize = 100 * 1024 * 1024L;
        // 计算需要上传的段数
        long partCount = fileSize % partSize == 0 ? fileSize / partSize : fileSize / partSize + 1;
        final List<PartEtag> partEtags = Collections.synchronizedList(new ArrayList<PartEtag>());
        // 执行并发上传段
        for (int i = 0; i < partCount; i++) {
            // 分段在文件中的起始位置
            final long offset = i * partSize;
            // 分段大小
            final long currPartSize = (i + 1 == partCount) ? fileSize - offset : partSize;
            // 分段号
            final int partNumber = i + 1;
            executorService.execute(
                    new Runnable() {
                        @Override
                        public void run() {
                            UploadPartRequest uploadPartRequest = new UploadPartRequest();
                            uploadPartRequest.setBucketName(bucketName);
                            uploadPartRequest.setObjectKey(objectKey);
                            uploadPartRequest.setUploadId(uploadId);
                            uploadPartRequest.setInput(inputStream);
                            uploadPartRequest.setPartSize(currPartSize);
                            uploadPartRequest.setOffset(offset);
                            uploadPartRequest.setPartNumber(partNumber);
                            UploadPartResult uploadPartResult;

                            try {
                                uploadPartRequest.setProgressListener(
                                        new ProgressListener() {
                                            @Override
                                            public void progressChanged(ProgressStatus status) {

                                                com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
                                                jsonObject.put("getInstantaneousSpeed", status.getInstantaneousSpeed()/(1024.0 * 1024.0) + "MB/s");//上传瞬时速率
                                                jsonObject.put("getAverageSpeed", status.getAverageSpeed()/(1024.0 * 1024.0) + "MB/s");//上传平均速率
                                                jsonObject.put("getTransferPercentage", status.getTransferPercentage()+"%");//上传进度百分比

                                                long timeout = 1;
                                                redisTemplate.opsForValue().set("process:"+ objectKey, jsonObject.toJSONString(), timeout, TimeUnit.DAYS);                                               
                                            }
                                        });
                                // 每上传1MB数据反馈上传进度
                                uploadPartRequest.setProgressInterval(1024 * 1024L);

                                uploadPartResult = ObsUtil.this.uploadPart(uploadPartRequest);
                                partEtags.add(
                                        new PartEtag(uploadPartResult.getEtag(), uploadPartResult.getPartNumber()));
                            } catch (ObsException e) {
                                e.printStackTrace();
                                log.error("ObsException", e);
                            }
                        }
                    });
        }
        // 等待上传完成
        executorService.shutdown();
        while (!executorService.isTerminated()) {
            executorService.awaitTermination(5, TimeUnit.SECONDS);
        }
        // 合并段
        CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectKey, uploadId, partEtags);
        obsClient.completeMultipartUpload(completeMultipartUploadRequest);
        return getFilePathInObs(path);
    }

参考

华为云对象存储服务OBS

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瑞瑞绮绮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值