全网最详细介绍如何实现图片存储阿里OSS实现资源持久化存储

news2024/11/24 16:00:49

什么是阿里云OSS

阿里云OSS(Object Storage Service,对象存储服务)是阿里云提供的一种存储服务,它支持任意类型的数据存储,如图片、视频、日志文件等。OSS以对象(Object)的形式组织数据,并存储在容器(Bucket)中。每个对象由其数据和元数据组成,对象被唯一地标识,使得用户可以在全球任何地方通过网络访问这些数据。

OSS的特点主要包括:

  1. 高可靠性和可用性:通过数据多副本机制确保数据安全,同时保证服务的高可用性。
  2. 可扩展性:用户可以根据需求无限扩展存储空间,不需要担心存储容量的限制。
  3. 灵活的访问控制:提供丰富的访问控制策略,支持细粒度的权限管理,确保数据安全。
  4. 成本效益:采用按需付费的方式,用户只需为实际使用的存储空间和数据传输等资源支付费用,无需前期投资。
  5. 易用性:提供了丰富的SDK和API接口,支持多种编程语言,便于用户集成和使用。
  6. 全球化服务:阿里云在全球多个地区提供OSS服务,用户可以根据业务需要选择数据存储的地理位置。

OSS适用于各种存储需求的场景,如网站静态资源存储、大数据分析、内容分发网络(CDN)的源站存储、企业级数据备份和灾难恢复等。它为用户提供了一种简单、安全、高效的数据存储解决方案。

Java代码如何实现存储

要是需要GPT Plus账号的小伙伴可以联系我~,不封号好用不贵,独享账号资源,一条龙服务

这里如何配置和购买阿里云oss就不介绍了,只是分享一下如何实现存储。而且使用阿里云的OSS也有很多种方式,这里分享一下其中一种就是使用阿里官方的SDK进行调用存储

导入阿里云OSS的SDK

<!--阿里云sdk-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.4.2</version>
        </dependency>

配置文件配置自己的配置文件信息

这里配置服务的信息即可

# 阿里云oss配置
# Aliyun OSS 配置
# 访问密钥ID,用于标识用户
aliyun.accessKeyId=XXXXXXXXXXXXXXXXXX
# 访问密钥密文,用于验证用户的身份
aliyun.accessKeySecret=XXXXXXXXXXXXXXXXXX
# OSS服务的访问域名
aliyun.oss.endpoint=XXXXXXXXXXXXXXXXXX
# OSS中的存储桶名称
aliyun.oss.bucketName=XXXXXXXXXXXXXXXXXX
#访问OSS服务的URL前缀
aliyun.oss.urlPrefix=XXXXXXXXXXXXXXXXXX

相关类逻辑代码编写

配置读写类
 * ClassName AliyunConfig.java
 * author 舒一笑
 * version 1.0.0
 * Description 阿里云OSS配置
 * createTime 2024031819:13:00
 */
@Data
@Configuration
public class AliyunConfig {
    // 地域节点
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.accessKeySecret}")
    private String accessKeySecret;

    @Value("${aliyun.oss.bucketName}")
    private String bucketName;
    @Value("${aliyun.oss.urlPrefix}")
    private String urlPrefix;
	
	// 这里我要说明一下就是如何你的生产环境配置比较严格那就需要在这个使用这个,不能使用spring自动注入ossClient这个客户端对象,不然就会出现相关问题,我就遇到的有配置的签名不匹配,将文件的上传路径地址误认为是桶名称等等报错。
    @Bean
    public OSSClient ossClient() {
        return new OSSClient(endpoint, accessKeyId, accessKeySecret);
    }
}
图片文件上传base64转MultipartFile工具类

/**
 * ClassName Base64DecodedMultipartFile.java
 * author 舒一笑
 * version 1.0.0
 * Description 图片文件上传base64转MultipartFile工具类
 * createTime 2024年03月18日 19:33:00
 */
public class Base64DecodedMultipartFile implements MultipartFile {
    private final byte[] imgContent;
    private final String header;

    public Base64DecodedMultipartFile(byte[] imgContent, String header) {
        this.imgContent = imgContent;
        this.header = header;
    }
    @Override
    public String getName() {
        return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1].split(";")[0];
    }

    @Override
    public String getOriginalFilename() {
        return getName();
    }

    @Override
    public String getContentType() {
        return header.split(":")[1].split(";")[0];
    }

    @Override
    public boolean isEmpty() {
        return imgContent == null || imgContent.length == 0;
    }

    @Override
    public long getSize() {
        return imgContent.length;
    }

    @Override
    public byte[] getBytes() {
        return imgContent;
    }

    @Override
    public InputStream getInputStream() {
        return new ByteArrayInputStream(imgContent);
    }

    @Override
    public void transferTo(File dest) throws IOException, IllegalStateException {
        try (FileOutputStream fos = new FileOutputStream(dest)) {
            fos.write(imgContent);
        }
    }
}

图片静态文件解析工具类
/**
 * ClassName Base64DecodedStaticFile.java
 * author 舒一笑
 * version 1.0.0
 * Description 图片静态文件解析工具类
 * createTime 2024年03月19日 13:08:00
 */
public class Base64DecodedStaticFile implements MultipartFile {
    private byte[] imgContent;

    public Base64DecodedStaticFile(byte[] imgContent) {
        this.imgContent = imgContent;
    }

    @Override
    public String getName() {
        return "filename";
    }

    @Override
    public String getOriginalFilename() {
        return "originalFilename.jpg";
    }

    @Override
    public String getContentType() {
        return "image/jpeg";
    }

    @Override
    public boolean isEmpty() {
        return imgContent == null || imgContent.length == 0;
    }

    @Override
    public long getSize() {
        return imgContent.length;
    }

    @Override
    public byte[] getBytes() throws IOException {
        return imgContent;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(imgContent);
    }

    @Override
    public void transferTo(java.io.File dest) throws IOException, IllegalStateException {
        // 这里根据你的需求实现文件传输的逻辑
    }
}
文件导入导出工具类
/**
 * ClassName FileUtil.java
 * author 舒一笑
 * version 1.0.0
 * Description 文件导入导出工具类
 * createTime 2024年03月19日 13:58:00
 */
@Component
public class FileUtil {

    @Autowired
    private AliyunConfig aliyunConfig;


    // 允许上传的格式
    private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg", ".jpeg", ".gif", ".png"};
    public PicUploadResult upload(MultipartFile multipartFile) {
        // 1. 对上传的图片进行校验: 这里简单校验后缀名
        // 另外可通过ImageIO读取图片的长宽来判断是否是图片,校验图片的大小等。
        // TODO 图片校验
        boolean isLegal = false;
        for (String type : IMAGE_TYPE) {
            if (StringUtils.endsWithIgnoreCase(multipartFile.getOriginalFilename(), type)) {
                isLegal = true;
                break;  // 只要与允许上传格式其中一个匹配就可以
            }
        }
        PicUploadResult picUploadResult = new PicUploadResult();
        // 格式错误, 返回与前端约定的error
        if (!isLegal) {
            picUploadResult.setStatus("error");
            return picUploadResult;
        }

        // 2. 准备上传API的参数
        String fileName = multipartFile.getOriginalFilename();
        String filePath = fileName;

        // 3. 上传至阿里OSS
        try {
            // 初始化OSSClient  
            /// 这里说明一下就是为了避免上面说的ossClient 问题另外一种写法,不使用spring自动注入,也不用配置类里面的ossClient,直接使用建造者模式直接build
            OSS ossClient = new OSSClientBuilder().build(aliyunConfig.getEndpoint(), aliyunConfig.getAccessKeyId(), aliyunConfig.getAccessKeySecret());
            ossClient.putObject(aliyunConfig.getBucketName(), filePath, new ByteArrayInputStream(multipartFile.getBytes()));
        } catch (IOException e) {
            e.printStackTrace();
            // 上传失败
            picUploadResult.setStatus("error");
            return picUploadResult;
        }

        // 上传成功
        picUploadResult.setStatus("done");
        // 文件名(即直接访问的完整路径)
        picUploadResult.setName(aliyunConfig.getUrlPrefix() + filePath);
        // uid
        picUploadResult.setUid(String.valueOf(System.currentTimeMillis()));
        return picUploadResult;
    }

    /**
     * 上传的目录
     * 目录: 根据年月日归档
     * 文件名: 时间戳 + 随机数
     * @param fileName
     * @return
     */
    private String getFilePath(String fileName) {
        return StringUtils.substringAfterLast(fileName, ".");
    }
}

阿里云oos响应配置类
/**
 * ClassName PicUploadResult.java
 * author 舒一笑
 * version 1.0.0
 * Description 阿里云oos响应配置类
 * createTime 2024年03月18日 19:20:00
 */
@Getter
@Setter
public class PicUploadResult {

    private String uid;

    private String name;

    private String status;

    private String response;

    private String linkProps;
}

调用逻辑类代码示例


// 首先自动注入一下
 @Autowired
    private FileUtil fileUtil;

这里是我的使用示例,展示一下调用的逻辑,有些代码是具有我项目中的业务实现部分不用理会

// 调用上传方法
            PicUploadResult uploadResult = fileUtil.upload(multipartFile);
            staticResourceService.saveSingleFileToServe(snapshotName, request.getSnapshot().replace("data:image/jpeg;base64,", "").replace("data:image/png;base64,", ""));
//            requestTemplate.setSnapshot("/" + UPLOAD_URL_PREFIX + '/' + snapshotName);
            requestTemplate.setSnapshot(uploadResult.getName());
            // 静态资源小图处理
            Gson gson = new Gson();
            PanelGroupRequest panelGroupRequest = gson.fromJson(request.getPanelInfo(), PanelGroupRequest.class);
//            panelGroupRequest.setPanelData(JSON.toJSONString(jsonArray));
            Map<String, String> resource = gson.fromJson(panelGroupRequest.getStaticResource(), Map.class);
            Map<String, String> imageUrl = new HashMap<>();
            for (String s : resource.keySet()) {
                String imageCode = resource.get(s);
                byte[] bytes = DatatypeConverter.parseBase64Binary(imageCode);
                PicUploadResult picUploadResult = fileUtil.upload(new Base64DecodedStaticFile(bytes));
                imageUrl.put(s, picUploadResult.getName());
            }
            // 数据库缩略图存储处理
            String staticResource = panelGroupRequest.getStaticResource();
            Map<String,String> staticResourceMap= gson.fromJson(staticResource, Map.class);
            for (String s : staticResourceMap.keySet()) {
                String s1 = staticResourceMap.get(s);
                if (s.contains("static-resource")) {
                    // 找到匹配项,修改为阿里云oos存储地址
                    for (String string : imageUrl.keySet()) {
                        if (string.equals(s)){
                            staticResourceMap.remove(s);
                            staticResourceMap.put(imageUrl.get(s), s1);
                        }
                    }
                }
            }
            String panelData = panelGroupRequest.getPanelData();
            JSONArray jsonArray = JSON.parseArray(panelData);
            // 遍历数组,寻找特定的 propValue 值
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject obj = jsonArray.getJSONObject(i);
                if (obj.containsKey("propValue") && obj.getString("propValue").contains("/static-resource/")) {
                    // 找到匹配项,添加前缀
                    obj.put("propValue", imageUrl.get(obj.get("propValue")));
                }
            }
            panelGroupRequest.setPanelData(JSON.toJSONString(jsonArray));
            panelGroupRequest.setStaticResource(gson.toJson(staticResourceMap));
            requestTemplate.setPanelInfo(gson.toJson(panelGroupRequest));
        }

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1531647.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【导论】数据可信流通 从运维信任到技术信任

信任 信任概念由于其抽象性和结构复杂性&#xff0c;在社会学、心理学、营销学、经济学、管理学等不同 的领域定义是不同的&#xff0c;但是达成共识的观点是&#xff1a;信任是涉及交易或交换关系的基础。 信任的基石 ①身份可确认&#xff0c;②利益可依赖&#xff0c;③能…

docker实战(3)

1, jdk17版本的dockerfile FROM eclipse-temurin:17-jre ADD ./target/ods-poc-0.0.1-SNAPSHOT.jar /home/app/app.jar WORKDIR /home/app ENV TZ Asia/Shanghai ENTRYPOINT ["java","-jar","/home/app/app.jar"] EXPOSE 8083dockerfile 1, …

数据结构的概念大合集02(线性表)

概念大合集02 1、线性表及其逻辑结构1.1 线性表的定义1.2 线性表的基本操作 2、线性表的顺序存储结构2.1 顺序表 3、线性表的链式存储3.1 链表3.1.1 头结点&#xff08;头指针&#xff09;&#xff0c;首指针&#xff0c;尾指针&#xff0c;尾结点3.1.2 单链表3.1.3 双链表3.1.…

Linux第79步_使用自旋锁保护某个全局变量来实现“互斥访问”共享资源

自旋锁使用注意事项:自旋锁保护的“临界区”要尽可能的短。 因此&#xff0c;在open()函数中申请“spinlock_t自旋锁结构变量”&#xff0c;然后在release()函数中释放“spinlock_t自旋锁结构变量”&#xff0c;这种方法就行不通了。如果使用一个变量“dev_stats”来表示“共享…

Nanya(南亚科技)DRAM芯片选型详解

一、DRAM产品选型 普通SDRAM只在时钟的上升期进行数据传输&#xff0c;DDR内存能够在时钟的上升期和下降期各传输一次数据&#xff0c;因此性能翻倍&#xff0c;被称为双倍速率同步动态随机存储器。因此DDR内存可以在与SDRAM相同的总线频率下达到更高的数据传输率。DDR是一种掉…

Pygame AttributeError no attribute ‘display‘问题及其解决方法

目录 前言 错误原因 解决方法 1. 确保正确安装 Pygame 2. 检查 Python 路径和 Pygame 模块位置 3. 修复模块命名冲突 4. 检查代码错误 5. 检查 Pygame 版本兼容性 代码示例 总结 前言 Pygame 是一个非常受欢迎的 Python 游戏开发库&#xff0c;它提供了丰富的功能和…

Linux 学习必备:CentOS 技能提升一站式平台!

介绍&#xff1a;CentOS是一种广泛使用的Linux发行版&#xff0c;特别受到企业用户的青睐。 首先&#xff0c;CentOS的全称是Community Enterprise Operating System&#xff0c;中文意思是“社区企业操作系统”。它起源于Red Hat Enterprise Linux (RHEL)的源代码&#xff0c;…

极智压缩 ——帮你高清无损压缩 JPG/PNG/GIF 图片!

引言 图片太大怎么办&#xff1f;图片该如何压缩&#xff1f;压缩后图片为什么变模糊了&#xff1f;屏幕前的你是不是经常被这些问题所困扰&#xff0c;腾讯云数据万象推出的图片极智压缩服务&#xff0c;可以帮你高清无损压缩 JPG/PNG/GIF 图片&#xff0c;解决你95%以上的图片…

解决虚拟机Linux ens33 没有 IP 地址

解决方法&#xff1a; 先进入 root 模式 sudo su 查看目录 ls /etc/sysconfig 找到上述文件夹 ls /etc/sysconfig/network-scripts/ 用 vim 打开 ifcfg-ens33 这个文件&#xff08;不都是这个名字&#xff0c;按这个方法找到这个文件就行&#xff09; vim /etc/sysconfig/netw…

学习笔记-华为IPD转型2020:3,IPD的实施

3. IPD的实施 1999 年开始的 IPD 转型是计划中的多个转型项目中的第一个&#xff08;Liu&#xff0c;2015&#xff09;。华为为此次转型成立了一个专门的团队&#xff0c;从大约20人开始&#xff0c;他们是华为第一产业的高层领导。董事会主席孙雅芳是这个团队的负责人。该团…

【算法与数据结构】深入二叉树实现超详解

文章目录 &#x1f4dd;前言&#x1f320; 接口函数✏️ 实现函数&#x1f309;创建树的新节点&#x1f320;通过前序遍历的数组构建二叉树&#x1f309;包装通过前序遍历的数组构建二叉树&#x1f320;二叉树的销毁&#x1f320;层次遍历&#x1f320;第一种实现&#xff1a;不…

如何在尽量不损害画质的前提下降低视频占内存大小?视频格式科普及无损压缩软件推荐

大家好呀&#xff0c;相比大家都有对视频画质和体积的追求和取舍&#xff0c;那么&#xff0c;如何才能在不牺牲画质的前提下&#xff0c;尽可能的将视频大小降低到极致呢&#xff1f; 首先我们要了解视频的构成&#xff0c;要想降低视频的体积大小&#xff0c;我们可以从以下几…

Learn OpenGL 22 高级光照与Gamma校正

高级光照 Blinn-Phong 冯氏光照不仅对真实光照有很好的近似&#xff0c;而且性能也很高。但是它的镜面反射会在一些情况下出现问题&#xff0c;特别是物体反光度很低时&#xff0c;会导致大片&#xff08;粗糙的&#xff09;高光区域。下面这张图展示了当反光度为1.0时地板会…

品牌方年度抖音店铺打造流量运营孵化方案

【干货资料持续更新&#xff0c;以防走丢】 品牌方年度抖音店铺打造流量运营孵化方案 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 PDF共120页&#xff08;完整资料包含以下内容&#xff09; 目录 抖音年度短视频直播运营规划方案 1. 帐号视频发布规划 问…

55、服务攻防——数据库安全RedisHadoopMysql未授权访问RCE

文章目录 常见服务应用的安全测试&#xff1a; 配置不当——未授权访问安全机制——特定安全漏洞安全机制——弱口令爆破攻击 应用服务安全测试流程&#xff1a; 判断服务开放情况——端口扫描&组合猜解等 端口扫描&#xff1a;服务开放&#xff0c;绑定端口没开放&#…

浅谈前端路由原理hash和history

1、认识前端路由 本质 前端路由的本质&#xff0c;是监听 url 地址或 hash 值的改变&#xff0c;来切换渲染对应的页面组件 前端路由分为两种模式 hash 模式 history 模式 两种模式的对比 2、hash 模式 &#xff08;1&#xff09;hash 定义 hash 模式是一种把前端路由的路…

管理类联考–复试–英文面试–问题--规划介绍原因做法--纯英文版

借鉴 https://www.bilibili.com/video/BV1Dk4y187zN/?p4&spm_id_from333.880.my_history.page.clickhttps://www.bilibili.com/video/BV1Dk4y187zN/?p4&spm_id_from333.880.my_history.page.click https://ttsreader.com/zh/https://ttsreader.com/zh/ 规划 视频版…

MyBatis3源码深度解析(十七)MyBatis缓存(一)一级缓存和二级缓存的实现原理

文章目录 前言第六章 MyBatis缓存6.1 MyBatis缓存实现类6.2 MyBatis一级缓存实现原理6.2.1 一级缓存在查询时的使用6.2.2 一级缓存在更新时的清空 6.3 MyBatis二级缓存的实现原理6.3.1 实现的二级缓存的Executor类型6.3.2 二级缓存在查询时使用6.3.3 二级缓存在更新时清空 前言…

Java基础 学习笔记八

控制语句 分支语句 switch switch语句完整格式 expression 中执行完必须是个值并且必须是 int 或者 枚举 或者 字符串类型break语句只要执行&#xff0c;switch就要结束default语句不是必须的&#xff0c;但是建议写上&#xff0c;这样程序更加健壮 switch(expression){//exp…

浅谈 电脑和车的对比

https://www.zhihu.com/question/547115488 电脑CPU与汽车发动机有哪些相同点与不同点&#xff1f; - 知乎 就想机械硬盘一样 我们的技术可能达不到 但是我们可以弯道超车 比如长江存储的SSD可以取代 以前的机械硬盘