Web项目利用OSS进行图像存储服务

news2024/11/24 16:49:06

一、OSS介绍        

        在Web项目中,一些常见的功能,比如展示图片,修改头像等,都需要进行图片的上传操作,但是如果是存储在Web服务器中,在读取图片的时候会占用比较多的资源,影响服务器的性能。

        常见的方式是使用OSS(Object Storage Service)存储图片或视频。

用户会先将图片上传至服务器,服务器这里担任的是中转的角色,前端界面发送请求到后端,后端需要保存数据(例如,图片的访问链接),返回给前端,后续需要浏览图片的时候,前端通过访问后端所返回的响应体中的链接到OSS中进行访问。

这种方式可以有效的节省服务器所需的资源,减轻带宽压力。

这里我们是使用七牛云OSS进行服务器直传(数据流的方式)的展示(有一定的免费存储空间),

详情可以参考操作文档:Java SDK_SDK 下载_对象存储 - 七牛开发者中心 (qiniu.com)

二、演示案例

2.1 引入Maven依赖

<dependency>
  <groupId>com.qiniu</groupId>
  <artifactId>qiniu-java-sdk</artifactId>
  <version>[7.13.0, 7.13.99]</version>
</dependency>

 2.2 默认提供的代码

        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.region0());
        cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
        //...其他参数参考类注释

        UploadManager uploadManager = new UploadManager(cfg);
        //...生成上传凭证,然后准备上传
        String accessKey = "your access key";
        String secretKey = "your secret key";
        String bucket = "your bucket name";

        //默认不指定key的情况下,以文件内容的hash值作为文件名
        String key = null;

        try {
            byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8");
            ByteArrayInputStream byteInputStream=new ByteArrayInputStream(uploadBytes);
            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(bucket);

            try {
                Response response = uploadManager.put(byteInputStream,key,upToken,null, null);
                //解析上传成功的结果
                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
                System.out.println(putRet.key);
                System.out.println(putRet.hash);
            } catch (QiniuException ex) {
                ex.printStackTrace();
                if (ex.response != null) {
                    System.err.println(ex.response);

                    try {
                        String body = ex.response.toString();
                        System.err.println(body);
                    } catch (Exception ignored) {
                    }
                }
            }
        } catch (UnsupportedEncodingException ex) {
            //ignore
        }

这里我们可以先对代码进行简单的修改,使其实现我们的功能,之后我们再一步步的优化,

2.2.1 修改Region配置类

通过观察,我们需要修改Region对象的配置类:

文档:

 

这里我们设置为autoRegion,它会自动帮我们绑定我们在七牛云上创建的OSS仓库的地址。

2.2.2 AK,SK,bucket name的查看和修改 

显而易见,还需要修改密钥,即AK,SK,和 bucket name。

AK,SK,在密钥管理处查看:

密钥管理界面如下: 

修改的话,这边是利用 @ConfigurationProperties从配置文件中获取,需要注意的是,使用改注解的时候,还需要给这些属性,配置对应的set方法才行:

当然,你也可以使用@Value从配置文件中获取属性。

yml配置文件如下:

 

 2.2.3 修改存储到OSS的文件名,存储的文件

到此,其实就可以实现一个简单的文件上传了:

 

2.2.4 代码实现

package com.fox;

import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

@SpringBootTest
@ConfigurationProperties(prefix = "oss")
public class OSSTest {

    private String accessKey;
    private String secretKey;

    private String bucket;

    public void setAccessKey(String accessKey) {
        this.accessKey = accessKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public void setBucket(String bucket) {
        this.bucket = bucket;
    }

    @Test
    public void testOss() {
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.autoRegion());
        cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
        //...其他参数参考类注释

        UploadManager uploadManager = new UploadManager(cfg);
        //...生成上传凭证,然后准备上传

        //默认不指定key的情况下,以文件内容的hash值作为文件名
        String key = "2022/fox.jpg";

        try {
//            byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8");
//            ByteArrayInputStream byteInputStream=new ByteArrayInputStream(uploadBytes);
            InputStream inputStream = new FileInputStream("C:\\Users\\86136\\Desktop\\Snipaste_2024-02-03_17-30-29.png");
            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(bucket);

            try {
                Response response = uploadManager.put(inputStream,key,upToken,null, null);
                //解析上传成功的结果
                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
                System.out.println(putRet.key);
                System.out.println(putRet.hash);
            } catch (QiniuException ex) {
                ex.printStackTrace();
                if (ex.response != null) {
                    System.err.println(ex.response);

                    try {
                        String body = ex.response.toString();
                        System.err.println(body);
                    } catch (Exception ignored) {
                    }
                }
            }
        } catch (Exception ex) {
            //ignore
        }

    }
}

三、实际项目中的OSS案例

其实跟上述过程差不多,只是将一些写死的数据,演变为可变的,并且返回响应给前端工程即可:

3.1 改进1:利用Lombok注解代替set方法

3.2 改进2:利用工具类动态生成文件名称

接受图片方法如下,该方法会返回给前端访问该图片的链接,ResponseResult为我自己定义的统一格式响应体。

    @Override
    public ResponseResult uploadImg(MultipartFile img) {
        //获取原始文件名
        String originalFilename = img.getOriginalFilename();
        //对原始文件名进行判断
        if (!originalFilename.endsWith(".png") && !originalFilename.endsWith(".jpg")) {
            throw new SystemException(AppHttpCodeEnum.FILE_TYPE_ERROR);
        }
        //如果判断通过那么就上传文件到OSS
        String filePath = PathUtils.generateFilePath(originalFilename);
        String url = uploadOss(img,filePath);

        return ResponseResult.okResult(url);
    }

PathUtils工具类如下,用于动态生成文件名:

package com.fox.utils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

public class PathUtils {

    public static String generateFilePath(String fileName){
        //根据日期生成路径   2022/1/15/
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
        String datePath = sdf.format(new Date());
        //uuid作为文件名
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //后缀和文件后缀一致
        int index = fileName.lastIndexOf(".");
        // test.jpg -> .jpg
        String fileType = fileName.substring(index);
        return new StringBuilder().append(datePath).append(uuid).append(fileType).toString();
    }
}

以下为uploadOss方法,key即为文件名,我们需要返回给前端的url,就是外链访问路径加上文件名即可:

bucket绑定的域名(外链访问域名获取)如下: 

3.3 总结:

代码实现:

package com.fox.service.impl;

import com.fox.domain.ResponseResult;
import com.fox.enums.AppHttpCodeEnum;
import com.fox.exception.SystemException;
import com.fox.service.UploadService;
import com.fox.utils.PathUtils;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;

@Service
@Data
@ConfigurationProperties(prefix = "oss")
public class OssUploadServiceImpl implements UploadService {

    private String accessKey;
    private String secretKey;
    private String bucket;

    @Override
    public ResponseResult uploadImg(MultipartFile img) {
        //获取原始文件名
        String originalFilename = img.getOriginalFilename();
        //对原始文件名进行判断
        if (!originalFilename.endsWith(".png") && !originalFilename.endsWith(".jpg")) {
            throw new SystemException(AppHttpCodeEnum.FILE_TYPE_ERROR);
        }
        //如果判断通过那么就上传文件到OSS
        String filePath = PathUtils.generateFilePath(originalFilename);
        String url = uploadOss(img,filePath);

        return ResponseResult.okResult(url);
    }
    private String uploadOss(MultipartFile imgFile, String filePath) {
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.autoRegion());
        cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
        //...其他参数参考类注释

        UploadManager uploadManager = new UploadManager(cfg);
        //...生成上传凭证,然后准备上传

        //默认不指定key的情况下,以文件内容的hash值作为文件名
        String key = filePath;

        try {
//            byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8");
//            ByteArrayInputStream byteInputStream=new ByteArrayInputStream(uploadBytes);
            InputStream inputStream = imgFile.getInputStream();
            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(bucket);

            try {
                Response response = uploadManager.put(inputStream,key,upToken,null, null);
                //解析上传成功的结果
                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
                System.out.println(putRet.key);
                System.out.println(putRet.hash);
                return "图片外链除去文件名的url地址"+key;
            } catch (QiniuException ex) {
                ex.printStackTrace();
                if (ex.response != null) {
                    System.err.println(ex.response);

                    try {
                        String body = ex.response.toString();
                        System.err.println(body);
                    } catch (Exception ignored) {
                    }
                }
            }
        } catch (Exception ex) {
            //ignore
        }
        return "2";
    }

}

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

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

相关文章

学习c语言,动态内存管理

malloc和calloc区别在于初始化

迅为RK3588开发板windows与开发板互传使用U盘进行拷贝

1 将 U 盘(U 盘的格式必须为 FAT32 格式&#xff0c;大小在 32G 以下)插到开发板的 usb 接口&#xff0c;串口打印信息如下所示&#xff0c;U 盘的设备节点是/dev/sdb4。U 盘的设备节点不是固定的&#xff0c;根据实际情况来查看设备节点。 2 输入以下命令挂载 U 盘&#xff0c…

2024年教资认定全流程详细图解✅

教资认定3月开始&#xff0c;大家别只顾着快乐过年&#xff0c;可以做好准备了&#xff01; ▶️材料准备&#xff1a; 有效期内的身份证原件学历证学位证普通话等级证书电子版个人照片&#xff08;个人近期白底免冠无头饰正面1寸证照。&#xff09;打印版填写完毕的个人承诺书…

感激沃尔玛跨境智星:轻松注册大量沃尔玛买家号的利器

最近&#xff0c;我急需大量沃尔玛买家号&#xff0c;但又担心账号之间可能存在关联问题。幸运的是&#xff0c;在我尝试使用沃尔玛跨境智星后&#xff0c;这一问题得到了解决。 首先&#xff0c;我要感谢这款软件提供的详细操作指南。通过访问沃尔玛官网并按照您的指引&#x…

【蓝桥杯冲冲冲】[NOIP2001 普及组] 装箱问题

蓝桥杯备赛 | 洛谷做题打卡day26 文章目录 蓝桥杯备赛 | 洛谷做题打卡day26题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示思路 题解代码我的一些话 [NOIP2001 普及组] 装箱问题 题目描述 有一个箱子容量为 V V V&#xff0c;同时有 n n n 个物品&#xff0c;每…

c++虚函数、静态绑定与动态绑定

首先说明&#xff0c;所谓绑定&#xff0c;就是指函数的调用 接下来&#xff0c;我们直接看一段代码来说明问题 class Base { public:Base(int data10):m_a(data){}void show(){cout<<"Base::show()"<<endl;}void show(int){cout<<"Base::sh…

引流技术-通过文件中增加联系方式并传播

文章目录 前言文档增加联系方式扩散网盘扩散自建网站借力 注意 前言 很多人在找资料的时候可能都遇到过下图情况&#xff1a; 1、文档最后面留一个自己的联系方式&#xff1b; 2、找的一堆文件中都有相同的情况&#xff1b; 3、一段时间全网搜到的很多相同文件也有这个联系方式…

springboot156基于SpringBoot+Vue的常规应急物资管理系统

基于SpringBootVue的常规应急物资管理系统的设计与实现 摘 要 1 ABSTRACT 2 第一章 绪论 3 1.1研究背景 3 1.2研究意义 3 1.3国内外研究现状 4 1.3.1国外研究现状 4 1.3.2国内研究现状 4 1.4研究内容与方法 5 1.4.1研究内容 5 1.4.2研究方法 5 1.5论文的组织结构 5…

3D力导向树插件-3d-force-graph学习002

一、实现效果&#xff1a;节点文字同时展示 节点显示不同颜色节点盒label文字并存节点上添加点击事件 二、利用插件&#xff1a;CSS2DRenderer 提示&#xff1a;以下引入文件均可在安装完3d-force-graph的安装包里找到 三、关键代码 提示&#xff1a;模拟数据可按如下格式填…

年终奖,还得是腾讯。。。

腾讯年终奖 什么是真正的好公司&#xff1f; 一年到头&#xff0c;出不了几次裁员等劳务纠纷的吃瓜新闻。 只有到年底了&#xff0c;才因为年终奖远高于行业水平&#xff0c;实在没法低调了&#xff0c;"被迫"上热搜。 最近网友爆料了腾讯头牌部门的年终奖&#xff1…

GPT用来润色论文\生成完整长篇论文\进行AI绘图,真的太香了!

详情点击公众号&#xff1a;技术科研吧 链接&#xff1a;GPT用来润色论文\生成完整长篇论文\进行AI绘图&#xff0c;真的太香了&#xff01; 一&#xff1a;AI领域最新技术 1.OpenAI新模型-GPT-5 2.谷歌新模型-Gemini Ultra 3.Meta新模型-LLama3 4.科大讯飞-星火认知 5.百…

C# CAD界面-自定义工具栏(二)

运行环境 vs2022 c# cad2016 调试成功 一、引用 acdbmgd.dllacmgd.dllaccoremgd.dllAutodesk.AutoCAD.Interop.Common.dllAutodesk.AutoCAD.Interop.dll using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.T…

CICD注册和使用gitlab-runner常见问题

1、现象 fatal: unable to access https://github.com/homebrew/brew/: 2、解决 git config --global --unset http.proxy git config --global --unset https.proxy 查看gitlab-runner是否成功&#xff1a; userusers-MacBook-Pro ~ % gitlab-runner -h 查看gitlab-run…

C# .Net学习笔记—— 异步和多线程(异常处理)

一、异常处理 1、下面for循环20个线程&#xff0c;到11&#xff0c;12号的时候执行失败&#xff0c;这里我也用了try catch来捕获异常。 private void button11_Click(object sender, EventArgs e){TaskFactory taskFactory new TaskFactory();List<Task> taskList ne…

c语言:贪吃蛇的实现

目录 贪吃蛇实现的技术前提&#xff1a; Win32 API介绍 控制台程序&#xff08;console&#xff09; 控制台屏幕上的坐标 GetStdHandle GetConsoleCursorInfo CONSOLE_CURSOR_INFO SetConsoleCursorInfo SetConsoleCursorPosition GetAsyncKeyState 宽字符的打印 …

企业级大数据安全架构(九)FreeIPA管理员密码忘记后如何修改

作者&#xff1a;楼高 1重置Directory Server管理员密码 1.1停止directory server服务 [rootipa schema]# start-dirsrv HDP-HADOOP 如果你不知道你的实例名&#xff0c;可以通过如下方式获取 1.2生成一个新的HASH密码 停止服务后使用pwdhash命令生成一个新的HASH密码 [r…

计算机毕业设计 | springboot 高校新生报到系统(附源码)

1&#xff0c;绪论 1.1 开发背景 学校新生报到仅仅靠原始的手工管理&#xff0c;面对大量的新生信息&#xff0c;无法有效率地将其中的重要部分提取出来&#xff0c;并做出相应的判断和处理。学校的决策只能依据报表数据&#xff0c;在浪费大量人力、物力的同时无法做到实时监…

WorkPlus构建安全高效的内网通讯平台,助力企业内部协作

在现代企业中&#xff0c;高效的内部沟通和协作是团队成功的关键。而内网通讯软件成为了实现内部沟通和协作的首选工具。作为一款领先的内网通讯软件&#xff0c;WorkPlus以其卓越的性能和安全的特性&#xff0c;助力企业打造高效内部沟通与协作的新时代。 为何选择WorkPlus作为…

【51单片机】开发板和单片机的介绍(2)

前言 大家好吖&#xff0c;欢迎来到 YY 滴单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

Pandoc+Typora文件格式转换

前言 上一期写了一篇名为体验PicGoGitHubjsDelivr搭建免费图床的文章&#xff0c;介绍了如何用Github作为图床&#xff0c;并使用了jsDelivr提供的免费CDN加速&#xff0c;配合markdown来写文章本地使用起来还不错&#xff0c;但是在把.md格式文章上传其他平台的时候遇到了问题…