SpringBoot通用模块--文件上传开发(阿里云OSS)

文件上传,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛,我们经常发抖音、发朋友圈都用到了文件上传功能。

实现文件上传服务,需要有存储的支持,那么我们的解决方案将以下几种:

  1. 直接将图片保存到服务的硬盘(springmvc中的文件上传)

    1. 优点:开发便捷,成本低

    2. 缺点:扩容困难

  2. 使用分布式文件系统进行存储

    1. 优点:容易实现扩容

    2. 缺点:开发复杂度稍大(有成熟的产品可以使用,比如:FastDFS,MinIO)

  3. 使用第三方的存储服务(例如OSS)

    1. 优点:开发简单,拥有强大功能,免维护

    2. 缺点:付费

在本项目选用阿里云的OSS服务进行文件存储。

因为在新增菜品时,需要上传菜品对应的图片(文件),包括后绪其它功能也会使用到文件上传,故要实现通用的文件上传接口。

文件上传,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛,我们经常发抖音、发朋友圈都用到了文件上传功能。

实现文件上传服务,需要有存储的支持,那么我们的解决方案将以下几种:

  1. 直接将图片保存到服务的硬盘(springmvc中的文件上传)

    1. 优点:开发便捷,成本低

    2. 缺点:扩容困难

  2. 使用分布式文件系统进行存储

    1. 优点:容易实现扩容

    2. 缺点:开发复杂度稍大(有成熟的产品可以使用,比如:FastDFS,MinIO)

  3. 使用第三方的存储服务(例如OSS)

    1. 优点:开发简单,拥有强大功能,免维护

    2. 缺点:付费

在本项目选用阿里云的OSS服务进行文件存储。(前面课程已学习过阿里云OSS,不再赘述)

定义OSS相关配置

在sky-server模块

注意冒号后面有空格!!!

application-dev.yml(开发环境下的配置文件,yml可以引用该文件的值,这样就不用把值写死)

sky:alioss:endpoint: oss-cn-hangzhou.aliyuncs.comaccess-key-id: LTAI5tPeFLzsPPT8gG3LPW64access-key-secret: U6k1brOZ8gaOIXv3nXbulGTUzy6Pd7bucket-name: sky-take-out

application.yml

spring:profiles:active: dev    #设置环境
sky:alioss:endpoint: ${sky.alioss.endpoint}access-key-id: ${sky.alioss.access-key-id}access-key-secret: ${sky.alioss.access-key-secret}bucket-name: ${sky.alioss.bucket-name}

细节:application-dev.yml是开发环境下的配置文件,yml可以引用该文件的值,这样就不用把值写死

读取配置信息

封装一个类专门存放配置信息

在sky-common模块中,已定义配置属性类(读取配置文件中对应的配置信息sky.alioss,并将其封装为一个类)

@ConfigurationProperties(prefix = "sky.alioss")

 细节:

  • 配置类存放位置:common的properties包下
  • 配置类的注解:@Component
  • @ConfigurationProperties(prefix = "sky.alioss")说明配置类对应的配置项

 生成OSS工具类对象

在sky-server模块

定义一个配置类用于自动创建OSS工具类对象(在此过程中为配置类的属性赋值了)

package com.sky.config;import com.sky.properties.AliOssProperties;
import com.sky.utils.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 配置类,用于创建AliOssUtil对象*/
@Configuration
@Slf4j
public class OssConfiguration {//自动启动@Bean//工具类对象只需要存在一个bean就好@ConditionalOnMissingBeanpublic AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties);return new AliOssUtil(aliOssProperties.getEndpoint(),aliOssProperties.getAccessKeyId(),aliOssProperties.getAccessKeySecret(),aliOssProperties.getBucketName());}
}

其中,AliOssUtil.java已在sky-common模块中定义

package com.sky.utils;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;/*** 文件上传** @param bytes* @param objectName* @return*/public String upload(byte[] bytes, String objectName) {// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {// 创建PutObject请求。ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}//文件访问路径规则 https://BucketName.Endpoint/ObjectNameStringBuilder stringBuilder = new StringBuilder("https://");stringBuilder.append(bucketName).append(".").append(endpoint).append("/").append(objectName);log.info("文件上传到:{}", stringBuilder.toString());return stringBuilder.toString();}
}

注意: 

        //文件访问路径规则 https://BucketName.Endpoint/ObjectNameStringBuilder stringBuilder = new StringBuilder("https://");stringBuilder.append(bucketName).append(".").append(endpoint).append("/").append(objectName);

定义文件上传通用接口

在sky-server模块中定义接口

package com.sky.controller.admin;import com.sky.constant.MessageConstant;
import com.sky.result.Result;
import com.sky.utils.AliOssUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.UUID;/*** 通用接口*/
@RestController
@RequestMapping("/admin/common")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {@Autowiredprivate AliOssUtil aliOssUtil;/*** 文件上传* @param file* @return*/@PostMapping("/upload")@ApiOperation("文件上传")public Result<String> upload(MultipartFile file){log.info("文件上传:{}",file);try {//原始文件名String originalFilename = file.getOriginalFilename();//截取原始文件名的后缀   dfdfdf.png substring只传一个参数,表示从该位置开始截取String extension = originalFilename.substring(originalFilename.lastIndexOf("."));//构造新文件名称String objectName = UUID.randomUUID().toString() + extension;//文件的请求路径String filePath = aliOssUtil.upload(file.getBytes(), objectName);return Result.success(filePath);} catch (IOException e) {log.error("文件上传失败:{}", e);}return Result.error(MessageConstant.UPLOAD_FAILED);}
}

细节:

MultipartFile file这个file一定是和前端请求的文件名保持一致的,不能随便取名。

 

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

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

相关文章

基于支持 GPT 的服务的初创公司

Kafkai&#xff1a;多语言长篇内容生成&#xff0c;AI写作的新趋势 介绍 随着生成式预训练 Transformer (GPT) 的出现&#xff0c;技术世界正在见证范式转变。 这种人工智能驱动的创新不仅仅是一种转瞬即逝的趋势&#xff0c;而是一种趋势。 它已成为科技行业的基石&#xff0c…

部分国企笔试总结

2024.3.30相城区某国企笔试 客观题&#xff0c;30分 类似考公行测题&#xff08;大部分&#xff09;部分计算机专业基础知识&#xff08;仅几题&#xff09; 主观题&#xff0c;70分 网络安全类一道C编程题&#xff1a;用户输入圆半径r&#xff0c;程序计算面积和周长并输出…

【C语言】简单介绍进制和操作符

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 本文简要介绍进制和操作符&#xff0c;愿能为您提供帮助&#xff01;文章…

异常的种类

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 Oracle 运行时错误可以分为 Oracle 错误和用户自定义错误&#xff0c;与此对应&#xff0c;根据异常产生的机制和原理&#xff0c;可将 Oracle 的系统异常分为 3 种 预定义…

【Linux】libgpiod使用方法

1、libgpiod库的移植 参见本人博客:libgpiod库的移植 2、libgpiod使用 2.1 打开GPIO芯片 一个GPIO芯片管理N个GPIO,每个GPIO芯片用结构体 ==gpiod_chip == 来表示。 1)以路径方式打开 例如GPIO芯片的路径为:/dev/gpiochip0 struct gpiod_chip *gpiod_chip_open(const …

使用VPN时,Java程序无法访问远程网络的解决办法

应用场景&#xff1a; 电脑连接VPN之后&#xff0c;Java程序无法连接远程服务&#xff0c;比如第三方接口、远程数据库连接、远程微服务等。我个人遇到的情况有连接海康威视SDK&#xff0c;influxdb以及一些微服务。 解决办法&#xff1a; 启动Java时加入参数&#xff1a;-D…

一个嵌入式ucosII系统的典型代码范例

在嵌入式系统开发中&#xff0c;uC/OS-II是一个非常流行的实时操作系统。它提供了许多功能&#xff0c;包括任务管理、信号量、消息邮箱、事件标志等&#xff0c;使得开发者能够更轻松地实现复杂的系统功能。在本文中&#xff0c;我们将展示一个完整的uC/OS-II示例代码&#xf…

41.Python从入门到精通—格式化日期 获取某月日历 Time 模块 日历(Calendar)模块 其他相关模块和函数

41.Python从入门到精通—格式化日期 获取某月日历 Time 模块 日历&#xff08;Calendar&#xff09;模块 其他相关模块和函数 格式化日期获取某月日历Time 模块日历&#xff08;Calendar&#xff09;模块其他相关模块和函数 格式化日期 在 Python 中&#xff0c;可以使用 strf…

比较好玩的车子 高尔夫6

https://www.sohu.com/a/484063087_221273 四万多如愿收获手动挡高尔夫6&#xff0c;可靠性、经济性、操控性兼顾_搜狐汽车_搜狐网 2.基本上其他人也不知道到底是什么相关的车子信息

基于单片机和ICL7135多档位数字电压表设计

**单片机设计介绍&#xff0c;基于单片机和ICL7135多档位数字电压表设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机和ICL7135的多档位数字电压表设计是一个结合了硬件与软件技术的综合性项目。这种设计旨在实现一…

四种锁(互斥锁,递归锁,读写锁,自旋锁)

1.互斥锁(mutex):互斥锁是最常见的一种锁,用来保护共享资源的互斥访问。一次只有一个线程可以获得互斥锁。如果其他线程试图获得已经被锁定的互斥锁,他们将被阻塞,直到锁被释放 2.递归锁(recursive lock):递归锁是一种特殊的互斥锁,允许同一个线程多次获得同一个锁,而不会导致死…

[lesson12]经典问题解析一

经典问题解析一 关于const的疑问 const常量的判别准则 只有用字面量初始化的const常量才会进入符号表使用其他变量初始化的const常量仍然是只读变量被volatile修饰的const常量不会进入符号表 在编译期间不能直接确定初始值的const标识符&#xff0c;都被作为只读变量处理 con…

Pnpm + Turbo 搭建 Web Component Monorepo 组件库

技术选型 使用 Pnpm Turbo 搭建 Web Component Monorepo项目 stencil-component-ui 组件库 pnpm 作为包管理器Turborepo 作为构建系统Vitepress 管理文档 pnpm 技术 什么是 pnpm? 它有哪些优势&#xff1f; pnpm 跟 npm、yarn一样&#xff0c;都是用于管理Node包依赖的管…

iOS App Store审核要求与Flutter应用的兼容性分析

本文探讨了使用Flutter开发的iOS应用能否上架&#xff0c;以及上架的具体流程。苹果提供了App Store作为正式上架渠道&#xff0c;同时也有TestFlight供开发者进行内测。合规并通过审核后&#xff0c;Flutter应用可以顺利上架。但上架过程可能存在一些挑战&#xff0c;因此可能…

云岚到家项目

一.项目介绍 云岚到家项目是一个家政服务o2o平台&#xff0c;互联网家政是继打车、外卖后的又一个风口&#xff0c;创业者众多&#xff0c;比如&#xff1a;58到家&#xff0c;天鹅到家等&#xff0c;o2o&#xff08;Online To Offline&#xff09;是将线下商务的机会与互联网…

openharmony launcher 调研笔记(03)UI 数据装配

最近在看launcher&#xff0c;把自己调研的点做个笔记&#xff0c;持续修改更新中&#xff0c;个人笔记酌情参考。 桌面上半部分包含父子逻辑&#xff1a; Column() { PageDesktopLayout(); } PageDesktopLayout->GridSwiper->Swiper->SwiperPage 1.PageDe…

25.11 MySQL 视图

1. 常见的数据库对象 对象描述表(TABLE)存储数据的逻辑单元, 以行和列的形式存在, 列就是字段, 行就是记录.数据字典系统表, 存放数据库相关信息的表. 数据通常由数据库系统维护, 程序员通常不可修改, 只可查看.约束(CONSTRAINT)执行数据校验的规则, 用于保证数据完整性的规则…

Python面向对象详解

文章目录 类和继承变量保护类装饰器 类和继承 Python虽然以函数式著称&#xff0c;但在Python中&#xff0c;万物皆对象&#xff0c;其对面向对象编程是有着非常不错的支持的。类是面向对象的核心数据类型&#xff0c;下面代码就创建了一个Person类。 class Person:count 0d…

2024马来西亚电商选品博览会

2024马来西亚电商选品博览会 展会概况 展会名称&#xff1a;2024马来西亚电商选品博览会 主办单位&#xff1a;广东进出口商会 时间:2024.11.29-12.1 地点&#xff1a;马来西亚国际贸易展览中心(MITEC) 展览面积&#xff1a;10000平方米 展会简介 2024马来西亚跨境电商选…

包和final.Java

1&#xff0c;包 包就是文件夹。用来管理不同功能的Java类&#xff0c;方便后期代码的维护。 &#xff08;1&#xff09;包名的规则是什么&#xff1f; 公司域名反写报的作用&#xff0c;需要全部英文小写&#xff0c;见名知意。com.itheima.domain &#xff08;2&#xff…