Springboot图片上传【本地+oss】

文章目录

  • 1 前端组件页面
  • 2 本地上传
  • 3 上传到阿里云oss
    • 3.1申请开通账号,做好先导准备
    • 3.2 开始使用


1 前端组件页面

使用的Vue+Element组件

在线cdn引入:

<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.16/vue.js"></script>
<!-- 引入样式 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<!-- 引入组件库 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">

组件页面,不是重点,不过多赘述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图片上传</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.16/vue.js"></script>
    <!-- 引入样式 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <!-- 引入组件库 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <style>
        .avatar-uploader .el-upload {
            border: 1px dashed #d9d9d9;
            border-radius: 6px;
            cursor: pointer;
            position: relative;
            overflow: hidden;
        }

        .avatar-uploader .el-upload:hover {
            border-color: #409EFF;
        }

        .avatar-uploader-icon {
            font-size: 28px;
            color: #8c939d;
            width: 178px;
            height: 178px;
            line-height: 178px;
            text-align: center;
        }

        .avatar {
            width: 178px;
            height: 178px;
            display: block;
        }
    </style>
</head>

<body>

    <div id="app">
        <el-upload class="avatar-uploader" action="http://localhost:8080/upload/image" name="image"
            :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
            <img v-if="imageUrl" :src="imageUrl" class="avatar">
            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
        </el-upload>
    </div>
</body>
<script>
    new Vue({
        el: '#app',
        data: {
            imageUrl: ''
        },
        methods: {
            handleAvatarSuccess(res, file) {
                // this.imageUrl = URL.createObjectURL(file.raw);
                this.imageUrl = res.data;
                //console.log(res.data);
                //console.log(res.msg);
                //console.log(file.raw.name);
                //console.log(file.raw.type);
            },
            beforeAvatarUpload(file) {
                const isLt2M = file.size / 1024 / 1024 < 2;
                if (!isLt2M) {
                    this.$message.error('上传头像图片大小不能超过 2MB!');
                }
                return isLt2M;
            }
        }
    })
</script>
</html>

注:
若是form表单,要注意数据提交的方式和格式:

<form action="/upload/upload" method="post" enctype="multipart/form-data">

</form>

2 本地上传

注意:当文件提交的name和后端的参数名称不对应时,可以通过@RequestParam("xxx"),来指定名称,如果名称不对应,那么获取到就是空字符串""而不是null

在这里插入图片描述

顾名思义,就是在运行相关代码的服务器上存储上传的数据【图片、音频、文本等】
本案例是将图片文件上传之后,存储到本地打包之后的target\classes\static\imgs目录下,这样在项目启动的过程中,就可以进行图片的存储和访问。

前端提交的路径:action=“http://localhost:8080/upload/image”,图片存储完成之后,给前端返回一个图片存储的访问路径:http://localhost:8080/imgs/+文件名
文件名:使用的是uuid随机字符串,拼接上截取到的文件后缀名。
【使用时间戳作为文件名并不太好,在并发情况下,若同一时间多用户存储,就会导致图片被覆盖】

注意:
1、使用MultipartFile image
2、使用getOriginalFilename()获取文件名
3、通过transferTo()方法写入

@RestController
@RequestMapping("/upload")
@Slf4j
public class UploadController {

    @PostMapping("/image")
    public HashMap<String,Object> fileUpload(MultipartFile image){
        HashMap<String, Object> map = new HashMap<>();
        String filename = image.getOriginalFilename();
        if(filename!=null&& !"".equals(filename)){
        	//文件最后一个“.”的位置
            int index = filename.lastIndexOf(".");
            //截取文件名
            String name = filename.substring(index);
            //拼接文件名
            String file = UUID.randomUUID().toString() + name;
            try {
                // 获取项目根目录
                String rootPath = System.getProperty("user.dir");
                // 拼接保存路径
                String savePath = rootPath + "/target/classes/static/imgs/" + file;
                File dest = new File(savePath);
                // 保存文件
                image.transferTo(dest);
                map.put("code",1);
                map.put("data","http://localhost:8080/imgs/"+file);
                map.put("msg","存储成功");
            } catch (IOException e) {
                map.put("code",0);
                map.put("msg","存储失败");
            }
        }else{
            map.put("code",0);
            map.put("msg","数据为空");
        }
        return map;
    }
}

3 上传到阿里云oss

3.1申请开通账号,做好先导准备

1、申请开通账号
2、创建bucket【制定存储空间】
3、获取自己的秘钥
在这里插入图片描述
在这里插入图片描述

最终需要准备好如下数据:
在这里插入图片描述
在yaml配置文件中写入上述数据内容,在后面的util中,使用@value注入。

3.2 开始使用

oss的使用是有专门的sdk文档的
在这里插入图片描述

这里以java为例https://help.aliyun.com/zh/oss/developer-reference/java-installation?spm=a2c4g.11186623.0.0.9e4c5b0frETztb

第一步,引入pom坐标

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.15.1</version>
</dependency>

如果使用的是Java 9及以上的版本,则需要添加JAXB相关依赖。添加JAXB相关依赖示例代码如下:

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.3</version>
</dependency>

第二步:快速上手,以上传文件为例
官方参考代码如下,在此基础上修改。

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import java.io.ByteArrayInputStream;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
        String objectName = "exampledir/exampleobject.txt";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

        try {
            String content = "Hello OSS";
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
        } 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();
            }
        }
    }
}

确保在yaml文件中,已经准备好了前提要准备中的数据
application.yml

spring:
  #放行静态资源
  resources:
    static-locations: classpath:/templates,classpath:/static
  # 图片大小限制
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 100MB

alioss:
  endpoint: oss-cn-xxxxxxxx.aliyuncs.com
  access-key-id: LTxxxxxxxxxxxFK16N5MF3
  access-key-secret: rUzSTxxxxxxxxxx6Gub05w97d07KN
  bucket-name: hylxxx

注:两个关键点
new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);//创建对象
putObject(bucketName, objectName, new ByteArrayInputStream(bytes));//云端提交存储数据

编写AliOssUtil类

package com.hyl.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;

/**
 * @author hyl
 * @version 1.0
 * @date 2024/5/3-16:29
 */
@Component
@Slf4j
public class AliOssUtil {

    @Value("${alioss.endpoint}")
    private String endpoint;
    @Value("${alioss.access-key-id}")
    private String accessKeyId;
    @Value("${alioss.access-key-secret}")
    private String accessKeySecret;
    @Value("${alioss.bucket-name}")
    private String bucketName;

    public String ossUpload(String objectName, byte[] bytes) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            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();
            }
        }
        //阿里云oss中文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

        log.info("文件上传到:{}", stringBuilder.toString());
        //返回图片存储路径
        return stringBuilder.toString();
    }
}

另一种注入方式,相对@Value的一种简化
在这里插入图片描述

编写controller

/**
 * @author hyl
 * @version 1.0
 * @date 2024/5/3-14:19
 */
@RestController
@RequestMapping("/upload")
@Slf4j
public class UploadController {
  	@Autowired
    private AliOssUtil aliOssUtil;

    /**
     * 文件上传
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public HashMap<String,Object>upload(@RequestParam("image") MultipartFile file){
        log.info("文件上传:{}",file);
        HashMap<String, Object> map = new HashMap<>();
        try {
            //原始文件名
            String originalFilename = file.getOriginalFilename();
            //截取原始文件名的后缀   dfdfdf.png
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            //构造新文件名称
            String objectName = UUID.randomUUID().toString() + extension;

            //文件的请求路径
            String filePath = aliOssUtil.ossUpload(objectName,file.getBytes());
            map.put("code",1);
            map.put("data",filePath);
            map.put("msg","存储成功");
            return map;
        } catch (IOException e) {
            log.error("文件上传失败:{}", e);
        }
        map.put("code",0);
        map.put("msg","存储失败");
        return map;
    }
}

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

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

相关文章

深入教程:在STM32上实现能源管理系统

引言 能源管理系统&#xff08;EMS&#xff09;在提高能源效率、减少能源消耗和支持可持续发展方面起着关键作用。本教程将介绍如何在STM32微控制器上开发一个能源管理系统&#xff0c;这种系统能够监控和控制能源使用&#xff0c;适用于家庭自动化、工业控制系统以及任何需要…

ARP欺骗使局域网内设备断网

一、实验准备 kali系统&#xff1a;可使用虚拟机软件模拟 kali虚拟机镜像链接&#xff1a;https://www.kali.org/get-kali/#kali-virtual-machines 注意虚拟机网络适配器采用桥接模式 局域网内存在指定断网的设备 二、实验步骤 打开kali系统命令行&#xff1a;ctrlaltt可快…

定点小数_

目录 定点小数表示和运算 定点小数的原码 定点小时加减法运算 定点小数 vs 定点整数 定点小数表示和运算 定点小数的原码 定点小数原反补转换 定点小时加减法运算 定点小数 vs 定点整数 定点小数原码依然是 取值范围等比数列 符号位 定点小数 同样的:

QT5之事件——包含提升控件

事件概述 信号就是事件的一种&#xff0c;事件由用户触发&#xff1b; 鼠标点击窗口&#xff0c;也可以检测到事件&#xff1b;产生事件后&#xff0c;传给事件处理&#xff0c;判断事件类型&#xff0c;后执行事件相应函数&#xff1b; 类似单片机的中断&#xff08;中断向量…

C语言 联合和枚举

目录 1. 联合体1.1 联合体类型的声明1.2 联合体变量的创建1.3 联合体的特点1.4 联合体在内存中的存储1.5 联合体使用举例 2. 枚举类型2.1 枚举类型的声明2.2 枚举变量的创建和初始化2.3 枚举类型的大小2.4 枚举类型的优点 正文开始 上次我们通过《C语言 结构体详解》学习了结构…

基于SpringBoot的饭店外卖平台的设计与实现

项目描述 这是一款基于SpringBoot的饭店外卖平台的系统 模块描述 用户端 登录 首页 商家信息 点餐 菜品列表 下单 订单列表 账号下单列表 个人中心 个人资料 修改信息 评论管理 评论菜品 查看评论 打赏骑手 打赏骑手 管理员 登录 菜品管理 修改 下架 订单列表 下单记录 菜品管理…

领域驱动设计(DDD)笔记(一)基本概念

文章链接 领域驱动设计&#xff08;DDD&#xff09;笔记&#xff08;一&#xff09;基本概念-CSDN博客领域驱动设计&#xff08;DDD&#xff09;笔记&#xff08;二&#xff09;代码组织原则-CSDN博客领域驱动设计&#xff08;DDD&#xff09;笔记&#xff08;三&#xff09;后…

C#知识|事件集中响应,多个按钮关联同一事件(实例练习)

哈喽&#xff0c;你好&#xff0c;我是雷工&#xff01; 本节学习窗体Controls集合、控件事件的统一关联及如何优化重复代码。 01 事件集中响应 原理&#xff1a;就是相同的控件&#xff0c;可以关联同一个事件响应方法。 02 示例演示 2.1、示例功能 该示例实现窗体中选择…

光伏光热热泵系统(PVT)介绍

伏光热PVT热泵是一种主动利用太阳辐射能的有效方式&#xff0c;其不仅能够进行光伏发电&#xff0c;还能够利用少量的电能提高热能的品位。太阳能PVT热泵除具有发电和制热的功能外&#xff0c;还可以制冷&#xff0c;其产生的冷能可用于夏季建筑室内温度的调节。 与此同时&…

STM32单片机wifi云平台+温度+烟雾+火焰+短信+蜂鸣器 源程序原理图

目录 1. 整体设计 2. 液晶显示 3. Ds18b20温度传感器 4. Mq2烟雾传感器 5. 火焰传感器传感器 6. 蜂鸣器驱动控制 7. 按键 8. Gsm短信模块 9. Esp8266wifi模块 10、源代码 11、资料内容 资料下载地址&#xff1a;STM32单片机wi…

Adobe-Premiere-CEP 扩展 入门-视频剪辑-去气口插件-Silence Remover

短视频&#xff0c;这两年比较火&#xff0c;不要再问为什么用Premiere&#xff0c;非常难用&#xff0c;为什么不用某影&#xff0c;某些国内软件非常接地气简单&#xff0c;又例如某音资深的视频短编辑就很好用了。。。 Premiere二次开发调试难&#xff0c;不如自己搞个cons…

展开说说:Android Fragment完全解析-卷三

本文章分析了Fragment的管理器FragmentManager、事务FragmentTransaction 、以及完整的声明周期和动态加载Fragment的原理解析。 1、Fragment管理器 FragmentManager 类负责在应用的 fragment 上执行一些操作&#xff0c;如添加、移除或替换操作&#xff0c;以及将操作添加到…

介绍BCD码

BCD码&#xff08;Binary-Coded Decimal‎&#xff09;&#xff0c;用4位 二进制数 来表示1位 十进制数 中的0~9这10个数码&#xff0c;是一种二进制的数字编码形式&#xff0c;用 二进制编码的十进制 代码。 BCD码这种编码形式利用了四个位元来储存一个十进制的数码&#xff0…

关于莫比乌斯变换属性梳理

文章目录 一、说明二、多视角看莫比乌斯变换2.1 从几何角度2.2 复分析中的莫比乌斯变换2.3 莫比乌斯变换运算组合2.4 莫比乌斯变换的不动点2.5 三个点决定一个莫比乌斯变换2.6 交叉比2.7 莫比乌斯变换的逆变换 三 莫比乌斯变换性质证明3.1 证明1&#xff1a;莫比乌斯变换将圆变…

最新SpringBoot项目地方废物回收机构管理系统

采用技术 最新SpringBoot项目地方废物回收机构管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 登录页面 后端管理员 管理员首页 员工管理 设…

微星主板安装双系统不能进入Ubuntu的解决办法

在微星主板的台式机上面依次安装了Windows11和Ubuntu22.04。在Ubuntu安装完成后重启&#xff0c;没有出现系统选择界面&#xff0c;直接进入了Windows11。怎么解决&#xff1f;方法如下&#xff1a; &#xff08;1&#xff09;正常安装Windows11 &#xff08;2&#xff09;安…

基于php+mysql+html简单图书管理系统

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、Php、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

需求规格说明书编制书(word原件)

1 范围 1.1 系统概述 1.2 文档概述 1.3 术语及缩略语 2 引用文档 3 需求 3.1 要求的状态和方式 3.2 系统能力需求 3.3 系统外部接口需求 3.3.1 管理接口 3.3.2 业务接口 3.4 系统内部接口需求 3.5 系统内部数据需求 3.6 适应性需求 3.7 安全性需求 3.8 保密性需…

# IDEA 复制项目 Module 出现 不同模块下的 Product 类报错

IDEA 复制项目 Module 出现 不同模块下的 Product 类报错 我们 用 IDEA 复制项目 Module 出现 不同模块下的 Product 类报错&#xff0c;发现复制的 module 名称没有改变或者 java 文件夹后面还有原项目 source root 字样&#xff0c;maven 父子项目没有标识等问题。 解决方法…

二叉树四种遍历方法

目录 树基本概念 二叉树二叉树的五种形态特殊二叉树二叉链表创建四种遍历方法代码实现 树 树是一个n个节点的有限集&#xff0c;当n0时称之为空树 基本概念 性质 1. 树的定义是递归的&#xff0c;树的定义中又用到了自身 2. 树的根节点没有前驱&#xff0c;除根结点外&#x…
最新文章