Springboot图片上传【本地+oss】

news2024/11/21 2:26:03

文章目录

  • 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.coloradmin.cn/o/1641693.html

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

相关文章

Simulink|【免费】虚拟同步发电机(VSG)惯量阻尼自适应控制仿真模型

目录 主要内容 仿真模型要点 2.1 整体仿真模型 2.2 电压电流双闭环模块 2.3 SVPWM调制策略 2.4 无功电压模块 2.5 自适应控制策略及算法 部分结果 下载链接 主要内容 该模型为simulink仿真模型&#xff0c;主要实现的内容如下&#xff1a; 随着风力发电、…

免费APP分发平台 - 一个指南和解析

数字化时代的APP分发平台 随着数字化进程的加速免费APP分发平台 - 一个指南和解析&#xff0c;移动应用&#xff08;APP&#xff09;市场正迅速扩大。在这个充满竞争的市场中免费APP分发平台 - 一个指南和解析&#xff0c;一个优秀的APP分发平台能够帮助开发者和商家更有效地触…

用keras识别狗狗

一、需求场景 从照片从识别出狗狗 from keras.applications.resnet50 import ResNet50 from keras.preprocessing import image from keras.applications.resnet50 import preprocess_input, decode_predictions import numpy as np# 加载预训练的ResNet50模型 model ResNet5…

网络知识点之—QoS

QoS&#xff08;Quality of Service&#xff0c;服务质量&#xff09;指一个网络能够利用各种基础技术&#xff0c;为指定的网络通信提供更好的服务能力&#xff0c;是网络的一种安全机制&#xff0c; 是用来解决网络延迟和阻塞等问题的一种技术。QoS的保证对于容量有限的网络来…

【matlab基础知识】(三)二维曲线绘制plot

x[-pi:0.0001:pi]; 选择较小步距 ysin(tan(x))-tan(sin(x));plot(x,y) 条件和函数值做一个点乘 x[-2:0.02:2];y1.1*sign(x).*(abs(x)>1.1)x.*(abs(x)<1.1);plot(x,y) 颜色&#xff0c;线形&#xff0c;曲线上的标志 由于0.01cosx波动太小&#xff0c;所以plotyy绘制多…

C语言 | Leetcode C语言题解之第64题最小路径和

题目&#xff1a; 题解&#xff1a; int minPathSum(int** grid, int gridSize, int* gridColSize) {int rows gridSize, columns gridColSize[0];if (rows 0 || columns 0) {return 0;}int dp[rows][columns];dp[0][0] grid[0][0];for (int i 1; i < rows; i) {dp[i…

【吃透Java手写】- Spring(上)-启动-扫描-依赖注入-初始化-后置处理器

【吃透Java手写】Spring&#xff08;上&#xff09;启动-扫描-依赖注入-初始化-后置处理器 1 准备工作1.1 创建自己的Spring容器类1.2 创建自己的配置类 ComponentScan1.3 ComponentScan1.3.1 Retention1.3.2 Target 1.4 用户类UserService Component1.5 Component1.6 测试类 2…

STM32——WWDG(窗口看门狗)

技术笔记&#xff01; 1.WWDG&#xff08;窗口看门狗&#xff09;简介 本质&#xff1a;能产生系统复位信号和提前唤醒中断的计数器。 特性&#xff1a; 递减的计数器&#xff1b; 当递减计数器值从 0x40减到0x3F时复位&#xff08;即T6位跳变到0&#xff09;&#xff1b; …

GPT-ArcGIS数据处理、空间分析、可视化及多案例综合应用

在数字化和智能化的浪潮中&#xff0c;GIS&#xff08;地理信息系统&#xff09;和GPT&#xff08;生成式预训练模型&#xff09;的结合正日益成为推动科研、城市规划、环境监测等领域发展的关键技术。GIS以其强大的空间数据处理、先进的空间分析工具、灵活的地图制作与可视化能…

OpenCV 实现重新映射(53)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV 实现霍夫圆变换(52) 下一篇 :OpenCV实现仿射变换(54) 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 一个。使用 OpenCV 函数 cv&#xff1a;&#xff1a;remap 实现简…

mysql-sql-练习题-4-标记(排名 条件判断)

标记 标记找规律连续登录2-7天用户建表排名找规律 最大连胜次数建表多次排名 找规律输出更多数据 标记计数 百分比 标记找规律 连续登录2-7天用户 建表 create table continuous_login(user_id1 integer comment 用户id,date_login date comment 登陆日期 ) comment 用户登录…

一加12/11/10/Ace2/Ace3手机上锁回锁BL无限重启黑屏9008模式救砖

一加12/11/10/Ace2/Ace3手机官方都支持解锁BL&#xff0c;搞机的用户也比较多&#xff0c;相对于其他品牌来说&#xff0c;并没有做出限制&#xff0c;这也可能是搞机党最后的救命稻草。而厌倦了root搞机的用户&#xff0c;就习惯性回锁BL&#xff0c;希望彻底变回官方原来的样…

约瑟夫问题新解法

前言 又碰到了约瑟夫问题&#xff0c;这样的题目本来用环形链表模拟的话就能做出来。然而&#xff0c;最近新学习了一种做法&#xff0c;实在是有点震惊到我了。无论是思路上&#xff0c;还是代码量上&#xff0c;都是那么的精彩。就想也震惊一下其他人。谁能想到原来模拟出来四…

Go-变量

可以理解为一个昵称 以后这个昵称就代指这些信息 var sg string "czy" 声明赋值 package mainimport "fmt"func main() {var sg string "陈政洋"fmt.Println(sg)var age int 73fmt.Println(age)var flag bool truefmt.Println(flag) } …

【JVM】内存调优——内存泄漏、内存溢出

内存调优 什么是内存泄漏、内存泄漏&#xff1f; 内存泄漏&#xff1a;在Java中如果不再使用一个对象&#xff0c;但是该对象依然在GC ROOT的引用链上&#xff0c;这个对象就不会被垃圾回收器回收。内存溢出&#xff1a;内存的使用量超过了Java虚拟机可以分配的上限&#xff…

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

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

栈的表达式求值中的应用——逆波兰表达式求值+中缀表达式转后缀表达式

文章目录 1. 逆波兰表达式&#xff08;后缀表达式&#xff09;求值思路讲解AC代码 2. 中缀表达式转后缀表达式分析方法总结 3. 中缀表达式求值 1. 逆波兰表达式&#xff08;后缀表达式&#xff09;求值 链接: link 这道题目叫做逆波兰表达式求值&#xff0c;那什么是逆波兰表…

使用PyTorch从头实现Transformer

前言 本文使用Pytorch从头实现Transformer&#xff0c;原论文Attention is all you need paper&#xff0c;最佳解读博客&#xff0c;学习视频GitHub项目地址Some-Paper-CN。本项目是译者在学习长时间序列预测、CV、NLP和机器学习过程中精读的一些论文&#xff0c;并对其进行了…

05月04日(周六)30场比赛前瞻

今日数据&#xff1a; 昨日复盘&#xff1a; 欧洲五大联赛指的是欧洲影响力及竞技水平排名前五的足球联赛&#xff0c;通常包括英格兰足球联赛&#xff08;The Premier League&#xff09;、西班牙足球甲级联赛&#xff08;La Liga&#xff09;、意大利足球甲级联赛&#xff0…

vue2人力资源项目3主页

主页权限验证 前置守卫开启进度条&#xff0c;后置守卫关闭进度条 import router from /router import nProgress from nprogress// 导入进度条&#xff08;模板自带&#xff09; import nprogress/nprogress.css// 导入进度条样式&#xff08;模板自带&#xff09; // 前置守…