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

一、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";
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EasyCVR智能视频监控平台云台降低延迟小tips

TSINGSEE青犀视频监控汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力&…

零基础爬什么值得买的榜单——爬虫练习题目一(答三)

一步一步似爪牙&#xff0c;先给爷爬一个! 引言分析数据上一节代码运行 工具&#xff1a;JSON 在线解析使用实操 获取其中一个数据添加代码知识点 结尾 引言 我也太能拖了 这个假期前确实有点懒惰 加上这个周末连班 不能去打篮球 腿没有得到充分的运动 像是千万只蚂蚁在爬一样…

AI Infra论文阅读之将流水线并行气泡几乎降到零(附基于Meagtron-LM的ZB-H1开源代码实现解读)

0x0. 前言 这篇论文对应的链接为&#xff1a;https://openreview.net/pdf?idtuzTN0eIO5 &#xff0c;最近被ICLR 2024接收&#xff0c;但不少AI Infra的同行已经发现了这个工作的价值&#xff0c;并且已经开源在 https://github.com/sail-sg/zero-bubble-pipeline-parallelis…

编写程序实现二叉树的创建,三种遍历自己销毁

#include <myhead.h>// 定义二叉树节点结构体 struct tree {char value; //二叉树的值struct tree* left; //左子树struct tree* right; //右子树 };// 创建节点 struct tree* create_node(int value) {//申请空间struct tree* new (struct tree*)malloc(sizeof(st…

[Python] opencv - 什么是直方图?如何绘制图像的直方图?

什么是直方图&#xff1f; 直方图是一种统计图&#xff0c;用于展示数据的分布情况。它将数据按照一定的区间或者组进行划分&#xff0c;然后计算在每个区间或组内的数据频数或频率&#xff08;即数据出现的次数或占比&#xff09;&#xff0c;然后用矩形或者柱形图的形式将这…

学成在线:媒体资源管理系统(MAM)

媒体资源管理系统(MAM) 媒体资源管理系统(Media Asset Management)是建立在多媒体、网络、数据库和数字存储等先进技术基础上的一个对各种媒体及内容进行数字化存储、管理以及应用的总体解决方案,可以满足媒体资源拥有者收集、保存、查找、编辑、发布各种信息的要求,为媒体资源…

Cannot resolve plugin org.apache.maven.plugins:maven-compiler-plugin:3.8.1

目录 【问题描述】maven环境报错 Cannot resolve plugin org.apache.maven.plugins:maven-compiler-plugin:3.8.1 【解决办法】 检查maven路径是否一致 路径一致的话&#xff0c;更改配置文件settings.xml的镜像源。 添加代码到 <mirrors> <!-- 阿里镜像 --> &l…

Security ❀ TCP异常报文详解

文章目录 1. TCP Out-Of-Order2. TCP Previous Segment Lost3. TCP Retransmission4. TCP Dup Ack XXX#X5. TCP Windows Update6. TCP Previous segment not captured7. 异常案例分析 TCP协议中seq和ack seq的联系&#xff1a; id4的http请求报文由客户端发向服务器&#xff0…

Transformer实战-系列教程1:Transformer算法解读1

&#x1f6a9;&#x1f6a9;&#x1f6a9;Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 Transformer实战-系列教程1&#xff1a;Transformer算法解读1 Transformer实战-系列教程2&#xff1a;Transformer算法解读2 现在最火的AI内容&#xff0c;chatGPT、视觉大模…

初识webpack(一)概念、入口配置、输出配置、loader等

目录 (一)概念 webpack的依赖图 (二)webpack的基本使用 (三)webpack的配置文件 1.入口(entry)配置 2.输出(output)配置 (三)loader 1.css文件处理 (1)安装css-loader和style-loader (2)在webpack.config.js中配置loader 2.less文件处理 3.postcss的使用 (1)安装…

mysql索引有哪些,如何分类

前言 按数据结构分类可分为&#xff1a;Btree索引、Hash索引、Full-text索引。 按物理存储分类可分为&#xff1a;聚簇索引、二级索引&#xff08;辅助索引&#xff09;。 按字段特性分类可分为&#xff1a;主键索引、普通索引、前缀索引。 按字段个数分类可分为&#xff1…

C++拷贝构造函数、赋值运算符重载

1.拷贝构造函数 拷贝构造函数的写法如图所示 调用方式如下 接下来我来说说它的特征 1.1特征 拷贝构造函数&#xff1a;只有单个形参&#xff0c;该形参是对本类类型对象的引用(一般常用const修饰)&#xff0c;在用已存在的类类型对象创建新对象时由编译器自动调用。 拷贝构造函…

推荐系统(Recommender Systems)

一、问题形式化 在接下来的内容中&#xff0c;我将开始讲解推荐系统的一些理论知识。我们从一个例子开始定义推荐系统&#xff0c;假使我们是一个电影供应商&#xff0c;我们有 5 部电影和 4 个用户&#xff0c;我们要求用户为电影打分 前三部电影是爱情片&#xff0c;后两部是…

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

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

歌声悠扬如往昔

有一首歌 - 朱晓琳&#xff08;网易云单曲&#xff09; 作词 : 陈彼得作曲 : 陈彼得有一首歌我想起你那时候微风轻轻有一首歌我想起你你的感觉温馨有多少的欢笑就有多少的忧伤 愿时光在这里停住(好景不常在)歌声悠扬如往昔哦哦哦咿咿咿有一首歌我和你词意朦胧旋律依稀唱一首歌…

云端录制直播流视频,上传云盘

前言 哪一天我心血来潮&#xff0c;想把我儿子学校的摄像头视频流录制下来&#xff0c;并保存到云盘上&#xff0c;这样我就可以在有空的时候看看我儿子在学校干嘛。想到么就干&#xff0c;当时花了一些时间开发了一个后端服务&#xff0c;通过数据库配置录制参数&#xff0c;…

Vue引入Axios

1.命令安装axios和vue-axios npm install axios --save npm install vue-axios --save 2.package.json查看版本 3.在main.js中引用 import axios from axios; import VueAxios from vue-axios; Vue.use(VueAxios,axios) 4.如何使用 &#xff08;初始化方法&#xff09; 将下列代…

微信小程序实现时间轴效果

目录 引言时间轴效果的应用场景微信小程序的优势时间轴效果的设计思路时间轴界面布局数据结构设计实现时间轴效果WXML结构设计WXSS样式设计JavaScript逻辑实现说明引言 时间轴效果的应用场景 时间轴效果作为一种独特且直观的信息展示形式,已经被广泛应用于各种场景中,提供了…

2023年最受欢迎的4款绘图软件全面评测!

无论你是一个专业的插画家&#xff0c;还是一个有创造力的人&#xff0c;想要随时记录生活的灵感&#xff0c;现在你只需要拿起平板电脑或打开电脑浏览器来描述你脑海中的图片。在这篇文章中&#xff0c;我们选择了四个强大、方便和易于使用的绘图软件&#xff0c;其中一个必须…

【算法】{画决策树 + dfs + 递归 + 回溯 + 剪枝} 解决排列、子集问题(C++)

文章目录 1. 前言2. 算法例题46.全排列78.子集 1. 前言 dfs问题 我们已经学过&#xff0c;对于排列、子集类的问题&#xff0c;一般可以想到暴力枚举&#xff0c;但此类问题用暴力解法 一般都会超时&#xff0c;时间开销过大。对于该种问题&#xff0c;重点在于尽可能详细的 画…