minio临时凭证直传切换到阿里云oss

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,内容安全 1000 次 1年
对象存储 OSS,恶意文件检测 1000次 1年
简介: minio临时凭证直传切换到阿里云oss

代码非常简单,像之前的实现:

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.ContentType;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.namaste.hsswobjectstorage.api.service.IOssService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.List;

import static java.util.stream.Collectors.*;

/**
 * AliOssServiceImpl
 *
 * @author achao@apache.org
 */
@Service
public class AliOssServiceImpl implements IOssService {

    @Resource
    private OSS ossClient;

    /**
     * @param rootPath bucket是配死的
     * @param fileName fileName
     * @return 预签名url
     */
    @Override
    public String getPresignedUrlPut(String bucket, String fileName) {
        var expiration = new Date(new Date().getTime() + 3600 * 1000L);
        var objectName = DateUtil.date().toDateStr() +
                FileNameUtil.UNIX_SEPARATOR +
                UUID.fastUUID() +
                DateUtil.date().toTimestamp() +
                StrPool.DOT +
                FileNameUtil.extName(fileName);
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, objectName, HttpMethod.PUT);
        request.setExpiration(expiration);
        request.setContentType(ContentType.OCTET_STREAM.getValue());
        return ossClient.generatePresignedUrl(request).toString();
    }

    @Override
    public void deleteBatch(List<String> fileUrls) {
        if (ObjectUtils.isEmpty(fileUrls)) {
            return;
        }
        var bucketObjectsMap = fileUrls.stream()
                .collect(groupingBy(
                        url -> url.substring(url.indexOf(StrPool.SLASH) + 2, url.indexOf(StrPool.DOT)),
                        mapping(url -> StrUtil.removePrefix(URLUtil.getPath(url), StrPool.SLASH),
                                toList())));
        bucketObjectsMap.entrySet().stream()
                .map(entry -> {
                    var req = new DeleteObjectsRequest(entry.getKey());
                    req.setKeys(entry.getValue());
                    return req;
                }).forEach(ossClient::deleteObjects);
    }

}

minio的实现:

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.core.text.StrPool;

import io.minio.RemoveObjectsArgs;
import io.minio.messages.DeleteObject;
import jakarta.annotation.Resource;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.minio.MinioConstants;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.ObjectUtils;

import java.time.Duration;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.*;

/**
 * OssServiceImpl
 *
 * @author VampireAchao<achao @ hutool.cn>
 * @since 2023/10/5
 */
//@Service
public class MinioOssServiceImpl implements IOssService {

    @Value("${camel.component.minio.presigned-url-expire}")
    private Duration presignedUrlExpire;
    @Resource
    private ProducerTemplate producerTemplate;
    @Lazy
    @Resource
    private IOssService ossService;

    @Override
    public String getPresignedUrlPut(String bucket, String fileName) {
        var objectName = DateUtil.date().toDateStr() +
                FileNameUtil.UNIX_SEPARATOR +
                UUID.fastUUID() +
                DateUtil.date().toTimestamp() +
                StrPool.DOT +
                FileNameUtil.extName(fileName);
        return String.valueOf(producerTemplate.requestBodyAndHeaders(
                "direct:createUploadLink", "",
                Map.of(MinioConstants.BUCKET_NAME, bucket,
                        MinioConstants.OBJECT_NAME, objectName,
                        MinioConstants.PRESIGNED_URL_EXPIRATION_TIME, presignedUrlExpire)));
    }

    @Override
    public void deleteBatch(List<String> fileUrls) {
        if (ObjectUtils.isEmpty(fileUrls)) {
            return;
        }
        var bucketObjectsMap = fileUrls.stream().map(path -> UrlBuilder.of(path).getPath())
                .collect(groupingBy(path -> path.getSegment(0), mapping(path -> {
                    path.getSegments().remove(0);
                    return String.join(StrPool.SLASH, path.getSegments());
                }, toList())));
        bucketObjectsMap.entrySet().stream()
                .map(entry -> RemoveObjectsArgs.builder()
                        .bucket(entry.getKey())
                        .objects(entry.getValue().stream().map(DeleteObject::new).toList())
                ).parallel()
                .forEach(args -> producerTemplate.sendBody("direct:deleteBatch", args));
    }

}

对应的service

import com.namaste.enums.GreenLabelEnum;
import org.dromara.streamquery.stream.core.variable.BoolHelper;

import java.util.List;

/**
 * IOssService
 *
 * @author VampireAchao<achao @ hutool.cn>
 * @since 2023/10/5
 */
public interface IOssService {

    /**
     * 获取预签名url上传
     *
     * @param bucket   桶
     * @param fileName fileName
     * @return 用于上传资源的url
     */
    String getPresignedUrlPut(String bucket, String fileName);

    /**
     * 批量删除
     *
     * @param fileUrls fileUrls
     */
    void deleteBatch(List<String> fileUrls);

    /**
     * 内容安全审查
     *
     * @param img 图片url
     * @return 审查结果
     */
    default GreenVO green(String img) {
        var result = GreenUtil.inspectImg(img, GreenLabelEnum.LIVE_STREAM_CHECK);
        var vo = GreenVO.of(result);
        if (BoolHelper.isFalsy(vo.getIsViolation())) {
            deleteBatch(List.of(img));
        }
        return vo;
    }

}

test case

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.core.net.url.UrlQuery;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.FileNotFoundException;
import java.util.List;

/**
 * OssServiceTest
 *
 * @author VampireAchao<achao @ hutool.cn>
 * @since 2023/10/5
 */
@SpringBootTest
class OssServiceTest {

    @Resource
    private IOssService ossService;

    @Test
    @SneakyThrows
    void getUploadSTSAndDeleteBatchTest() {
        var presignedUrl = ossService.getPresignedUrlPut("test", "test.txt");
        Assertions.assertNotNull(presignedUrl);
        var content = "Hello, Minio! Again!";
        try (var response = HttpUtil.createRequest(Method.PUT, presignedUrl)
                .body(content, "application/octet-stream").execute()) {
            Assertions.assertTrue(response.isOk());
        }
        var urlBuilder = UrlBuilder.of(presignedUrl).setQuery(new UrlQuery());
        Assertions.assertEquals(content,
                IoUtil.readUtf8(urlBuilder.toURL().openStream()));
        ossService.deleteBatch(List.of(urlBuilder.toString()));
        Assertions.assertThrows(FileNotFoundException.class,
                () -> IoUtil.readUtf8(urlBuilder.toURL().openStream()));
    }

    @Test
    void greenNormalTest() {
        var url = [foo];
        var bytes = IoUtil.readBytes(URLUtil.getStream(URLUtil.url(url)));
        var preUrl = ossService.getPresignedUrlPut("test", "normal.jpg");
        try (var response = HttpUtil.createRequest(Method.PUT, preUrl).contentType(ContentType.OCTET_STREAM.getValue()).body(bytes).execute()) {
            Assertions.assertTrue(response.isOk());
            var urlBuilder = UrlBuilder.of(preUrl).setQuery(new UrlQuery());
            Assertions.assertEquals(bytes.length, IoUtil.readBytes(URLUtil.getStream(urlBuilder.toURL())).length);
            var imgUrl = urlBuilder.toURL().toString();
            var greenVO = ossService.green(imgUrl);
            Assertions.assertFalse(greenVO.getIsViolation());
            Assertions.assertThrows(FileNotFoundException.class,
                    () -> IoUtil.readUtf8(urlBuilder.toURL().openStream()));

        }
    }


    @Test
    void greenYellowTest() {
        var url = [bar];
        var bytes = IoUtil.readBytes(URLUtil.getStream(URLUtil.url(url)));
        var preUrl = ossService.getPresignedUrlPut("test", "normal.jpg");
        try (var response = HttpUtil.createRequest(Method.PUT, preUrl).body(bytes).execute()) {
            Assertions.assertTrue(response.isOk());
            var urlBuilder = UrlBuilder.of(preUrl).setQuery(new UrlQuery());
            Assertions.assertEquals(bytes.length, IoUtil.readBytes(URLUtil.getStream(urlBuilder.toURL())).length);
            var imgUrl = urlBuilder.toURL().toString();
            var greenVO = ossService.green(imgUrl);
            Assertions.assertTrue(greenVO.getIsViolation());
            var readBytes = IoUtil.readBytes(URLUtil.getStream(urlBuilder.toURL()));
            Assertions.assertEquals(readBytes.length, bytes.length);
        }
    }

}
相关实践学习
通义万相文本绘图与人像美化
本解决方案展示了如何利用自研的通义万相AIGC技术在Web服务中实现先进的图像生成。
相关文章
|
30天前
|
存储 运维 安全
阿里云国际站OSS与自建存储的区别
阿里云国际站对象存储OSS提供海量、安全、低成本的云存储解决方案。相比自建存储,OSS具备易用性强、稳定性高、安全性好、成本更低等优势,支持无限扩展、自动冗余、多层防护及丰富增值服务,助力企业高效管理数据。
|
1月前
|
存储 域名解析 前端开发
震惊!不买服务器,还可以用阿里云国际站 OSS 轻松搭建静态网站
在数字化时代,利用阿里云国际站OSS可低成本搭建静态网站。本文详解OSS优势及步骤:创建Bucket、上传文件、配置首页与404页面、绑定域名等,助你快速上线个人或小型业务网站,操作简单,成本低廉,适合初学者与中小企业。
|
1月前
|
存储 安全 API
某网盘不好用?有没有类似某网盘的存储软件?阿里云国际站 OSS:云存储的全能助手,你 get 了吗?
在数据爆炸时代,阿里云国际站OSS提供海量、安全、低成本的云存储服务,支持多种数据类型存储与灵活访问,助力企业与个人高效管理数据,降低存储成本。开通简便,操作友好,是理想的云端数据解决方案。
|
4月前
|
存储 Java Linux
SpringBoot × MinIO 极速开发指南:对象存储服务高可用实战
生成临时访问URL接口和文件预览其实是同一个方法,只是文件预览内定了七天访问,而这个方法可以自行制定,单位是秒。方法,所以返回的是地址信息,但是可以通过dubug看到Bucket中的属性,确实是当前所有桶信息。配置类中奖MinIOClient客户端注入到Springboot中。MinIO集群的在Linux上的部署可以参考:​​​​​​​。Nginx代理MinIO集群可以参考:​​​​​​​。从Bucket源码可以看出,并没有实现。
431 0
|
7月前
|
SQL 分布式计算 Serverless
基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用
基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用
152 0
|
机器学习/深度学习 人工智能 专有云
人工智能平台PAI使用问题之怎么将DLC的数据写入到另一个阿里云主账号的OSS中
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
10月前
|
存储 Java API
开源对象存储服务(MinIO),正在备受欢迎!
本文介绍了MinIO,一个高性能、开源的对象存储服务器,兼容Amazon S3 API,适合存储大量非结构化数据。文章详细讲解了MinIO在Java中的使用方法,包括添加依赖、初始化客户端、基本操作(创建桶、上传/下载/删除对象)和高级功能(设置桶策略、使用预签名URL),并提供了Spring Boot集成MinIO的示例。
924 4
|
10月前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
存储 机器学习/深度学习 弹性计算
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
168 1

热门文章

最新文章