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;}@Testpublic 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为我自己定义的统一格式响应体。

    @Overridepublic ResponseResult uploadImg(MultipartFile img) {//获取原始文件名String originalFilename = img.getOriginalFilename();//对原始文件名进行判断if (!originalFilename.endsWith(".png") && !originalFilename.endsWith(".jpg")) {throw new SystemException(AppHttpCodeEnum.FILE_TYPE_ERROR);}//如果判断通过那么就上传文件到OSSString 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 -> .jpgString 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;@Overridepublic ResponseResult uploadImg(MultipartFile img) {//获取原始文件名String originalFilename = img.getOriginalFilename();//对原始文件名进行判断if (!originalFilename.endsWith(".png") && !originalFilename.endsWith(".jpg")) {throw new SystemException(AppHttpCodeEnum.FILE_TYPE_ERROR);}//如果判断通过那么就上传文件到OSSString 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.hqwc.cn/news/452249.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Node需要了解的知识

Node能执行javascript的原因。 浏览器之所以能执行Javascript代码&#xff0c;因为内部含有v8引擎。Node.js基于v8引擎封装&#xff0c;因此可以执行javascript代码。Node.js环境没有DOM和BOM。DOM能访问HTML所有的节点对象&#xff0c;BOM是浏览器对象。但是node中提供了cons…

音箱、功放播放HDMI音频解决方案之HDMI音频分离器HHA

HDMI音频分离器HHA简介 HDMI音频分离器HHA具有一路HDMI信号输入&#xff0c;转换成一路HDMI信号、一路5.1光纤音频信号、一路5.1 SPDIF/同轴音频信号和一路模拟左右声道立体声信号输出&#xff0c;同时还支持EDID存储及兼容HDCP功能&#xff1b;分辨率最高支持1920*1080p&#…

Ainx框架实现 一

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于Ainx系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基础系列…

QGraphicsScene中显示GIF动图,GIF图片在场景中移动

文章目录 效果图引言显示GIF图片&#xff08;方法一&#xff09;显示GIF图片&#xff08;方法二&#xff09;GIF图片在场景中运动 效果图 引言 当我们想在QGraphicsScene显示或者说绘制一张GIF动图时&#xff0c;该如何处理&#xff1f;Qt中的 QGraphicsItem 的 paint 函数中&…

【开源】WordPress一键崩溃宕机插件(整活娱乐)

插件介绍 可一键实现Wordpress崩溃宕机的整活向插件&#xff08;请勿用于非法途径&#xff0c;仅供整活娱乐&#xff09;。鼓励关注网站性能的提升&#xff0c;以提供更好的用户体验&#xff0c;提倡为用户提供良好体验和高效速度的原则。 介绍 长期以来&#xff0c;人们都在…

暗黑童话《潘神的迷宫》赏析

故事背景 《潘神的迷宫》是一部由吉尔莫德尔托罗执导的墨西哥电影&#xff0c;讲述了一个结合了幻想、战争、童话和现实主义元素的故事。影片发生在西班牙内战期间&#xff0c;主要通过一名名叫奥菲莉亚的女孩的视角来展开。 故事梗概&#xff1a; 奥菲莉亚和她怀孕的母亲卡…

如何排查常规软件问题 - 面向 Linux 初级用户的教程

笔者从 14 年做开源软件以来&#xff0c;接触了众多 Linux 新手用户&#xff0c;这里我为这类用户总结了一些常见的问题排查方法&#xff0c;希望能帮助到大家。如果你已经工作多年&#xff0c;对于下面提到的思路和方法应该非常熟悉&#xff0c;如果对某一条感到陌生&#xff…

Stable Diffusion 模型下载:ReV Animated

模型介绍 该模型能够创建 2.5D 类图像生成。此模型是检查点合并&#xff0c;这意味着它是其他模型的产物&#xff0c;以创建从原始模型派生的产品。 条目内容类型大模型基础模型SD 1.5来源CIVITAI作者s6yx文件名称revAnimated_v122EOL.safetensors文件大小5.13GB 生成案例 …

瑞_23种设计模式_工厂模式

文章目录 1 什么是工厂模式案例案例代码 2 简单工厂模式&#xff08;Simple Factory&#xff09;2.1 简单工厂模式的结构2.2 案例改进——简单工厂模式2.3 案例改进代码实现2.4 简单工厂模式优缺点2.5 拓展——静态工厂 3 工厂方法模式&#xff08;Factory Method&#xff09;★…

【爬虫实战】全过程详细讲解如何使用python获取抖音评论,包括二级评论

简介&#xff1a; 前两天&#xff0c;TaoTao发布了一篇关于“获取抖音评论”的文章。但是之前的那一篇包涵的代码呢仅仅只能获取一级评论。虽然说抖音的一级评论挺精彩的了&#xff0c;但是其实二级评论更加有意思&#xff0c;同时二级评论的数量是很多。所以二级评论是非常值…

React Native学习记录

一、创建RN项目的时候是空文件夹的问题 1.使用npx react-native init RNDemos初始化项目的时候&#xff0c;会报错&#xff0c;模版错误&#xff0c;然后创建出来一个空的文件夹 2.如果出现这种情况&#xff0c;需要设置npm install -g react-native-cli 3.安装完成以后再次初…

关于Django部署

首先了解一下开发环境服务器跟生产环境服务器有何不同。 一、我们通过 python manage.py runserver 启动开发环境服务器&#xff0c;这条命令背后做了哪些事情&#xff1f; 1、首先加载Django项目的设置&#xff08;settings&#xff09; 2、检查数据库迁移&#xff0c;确保数…