当前位置: 首页 > news >正文

SpringBoot+OSS文件(图片))上传

SpringBoot整合OSS实现文件上传

以前,文件上传到本地(服务器,磁盘),文件多,大,会影响服务器性能

如何解决? 使用文件服务器单独存储这些文件,例如商业版–>七牛云存储,阿里云OSS,腾讯云cos等等

也可以自己搭建文件服务器(FastDFS,minio)

0 过程中需要实名认证

1 开通阿里云OSS

image-20240719152009607

2 创建bucket

image-20240719152243439

其他不用管,直接完成即可

3 获取AccessKeyId、AccessKeySecret

image-20240719152336136

image-20240719152737253

墙裂建议,保存好此文件,因为后续无法再查看,只能删除重建

4 获取外网访问域名

image-20240719153351723

Endpoint(地域节点): xxxxx

Bucket 域名 : xxxxx

5 创建文件夹

image-20240719153550710

oss中存储在app/upload下

6 添加依赖

  		<!-- 阿里云OSS--><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency>

7 封装常量类

根据自己实际情况改变

public class AliyunOSSConstants {// OSS唯一keypublic static final String ASSCESS_KEY_ID = "你的ASSCESS_KEY_ID";// OSS唯一key秘钥public static final String ASSCESS_KEY_SECRET = "你的ASSCESS_KEY_SECRET";// 地域节点public static final String END_POINT = "你的地域节点";// Bucket名称public static final String BUCKET_NAME = "你的Bucket名称";// 文件一级路径public static final String FILE_DIR = "oss中创建的文件路径";// 文件访问域名public static final String COMMON_URL = "这个是后续访问的公共路径前缀";}

8 封装工具类

package com.qf.util;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CreateBucketRequest;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;/*** --- 天道酬勤 ---** @author QiuShiju* @date 2024/12/08* @desc*/
public class AliyunOSSUtil {/*** 上传文件*/public static String upLoad(MultipartFile file) {System.out.println("------OSS文件上传开始--------" );String endPoint = AliyunOSSConstants.END_POINT;String accessKeyId = AliyunOSSConstants.ASSCESS_KEY_ID;String accessKeySecret = AliyunOSSConstants.ASSCESS_KEY_SECRET;String bucketName = AliyunOSSConstants.BUCKET_NAME;String fileDir = AliyunOSSConstants.FILE_DIR;SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");String dateStr = format.format(new Date( ));String fileUrl = null;OSS client = new OSSClientBuilder( ).build(endPoint, accessKeyId, accessKeySecret);try {// 判断容器是否存在,不存在就创建if (!client.doesBucketExist(bucketName)) {client.createBucket(bucketName);CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);client.createBucket(createBucketRequest);}String originalFilename = file.getOriginalFilename( );String suffix = originalFilename.substring(originalFilename.indexOf("."));// 设置文件路径和名称fileUrl = fileDir + "/" + (dateStr + "/" + UUID.randomUUID( ).toString( ).replace("-", "") + suffix);System.out.println("fileUrl:" + fileUrl);// 上传文件PutObjectResult result = client.putObject(new PutObjectRequest(bucketName, fileUrl, file.getInputStream( )));// 设置权限(公开读)client.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);if (result != null) {System.out.println("resp:" + result);System.out.println("------OSS文件上传成功------" + AliyunOSSConstants.COMMON_URL + fileUrl);}} catch (OSSException oe) {oe.printStackTrace();} catch (ClientException ce) {ce.printStackTrace();} catch (IOException e) {e.printStackTrace( );} finally {if (client != null) {client.shutdown( );}}return AliyunOSSConstants.COMMON_URL + fileUrl;}/*** 删除文件*/public static String delete(String fileUrl) {System.out.println("------OSS文件删除开始--------" + fileUrl);String endPoint = AliyunOSSConstants.END_POINT;String accessKeyId = AliyunOSSConstants.ASSCESS_KEY_ID;String accessKeySecret = AliyunOSSConstants.ASSCESS_KEY_SECRET;String bucketName = AliyunOSSConstants.BUCKET_NAME;OSS client = new OSSClientBuilder( ).build(endPoint, accessKeyId, accessKeySecret);try {client.deleteObject(bucketName, fileUrl);System.out.println("------OSS文件删除成功------" + AliyunOSSConstants.COMMON_URL + fileUrl);} catch (OSSException oe) {oe.printStackTrace();} catch (ClientException ce) {ce.printStackTrace();} finally {if (client != null) {client.shutdown( );}}return AliyunOSSConstants.COMMON_URL + fileUrl;}
}

9 接口测试

@RestController
public class UploadController {/*** 演示上传文件到OSS*/@PostMapping("/upload")public R upload(MultipartFile file){String filePath = AliyunOSSUtil.upLoad(file);return R.ok(filePath);}}

10 前端

<template><div><h2>文件上传</h2><!--:http-request="uploadFile"  是用来覆盖默认的action的请求路径的action=""不能删除,因为是<el-upload>组件必填参数,不填会报错-->  <el-uploadclass="upload-demo"dragaction="":http-request="uploadFile"  :on-change="handleChange"multiple><i class="el-icon-upload"></i><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div></el-upload><div><!-- 上传后展现图片的地方 -->  <img :src="fileSrc" width="200px"></div></div></template><script>
import {uploadPicture} from '@/api/upload'
export default {data(){return{file:null,fileSrc:null}},methods:{handleChange(file){this.file = file.raw;},uploadFile(){const file = this.file;// FormData是js对象,用于存储表单数据  const formData = new FormData();formData.append("file", file); // 由后端接口决定,后端参数叫fileuploadPicture(formData).then((res) => {this.$message({message: "上传成功",type: "success",});this.fileSrc = res.dataconsole.log("fileSrc",this.fileSrc)});}}
}
</script><style scoped lang="scss"></style>

使用:http-request指定文件上传的函数,原有的action、:before-upload、:on-success等不起作用。但删去action可能有报错,所以还是写了action=“”。

uploadPicture()是封装的函数,在upload.js中

import request from '@/utils/request'export function uploadPicture(data) {return request({url: '/upload',method: 'post',data})
}

11 测试即可

image-20240719162138204

12. 后续,需要改造后端

现在只是上传成功

还需要将上传好的图片地址存储到数据库,后续查询时查出地址,在前端展现

提示: 数据库存储图片地址时不要太长,可以只存储重要信息. 公共部分可以等从数据库查询出后再拼接展现给前端

image-20241204104005570

相关文章:

SpringBoot+OSS文件(图片))上传

SpringBoot整合OSS实现文件上传 以前,文件上传到本地(服务器,磁盘),文件多,大,会影响服务器性能 如何解决? 使用文件服务器单独存储这些文件,例如商业版–>七牛云存储,阿里云OSS,腾讯云cos等等 也可以自己搭建文件服务器(FastDFS,minio) 0 过程中需要实名认证 … 1 开…...

docker镜像构建企业级示例

华子目录 示例&#xff08;在centos容器中源码编译nginx&#xff08;单介构建&#xff09;&#xff09;包准备为centos容器提供网络源添加企业7的ISO文件 提交为新的centos镜像编写dockerfile文件构建镜像如何优化自己构建的镜像大小多介构建 ldd命令基本用法示例 镜像优化方案…...

【源码】Sharding-JDBC源码分析之SQL中读写分离动态策略、数据库发现规则及DatabaseDiscoverySQLRouter路由的原理

Sharding-JDBC系列 1、Sharding-JDBC分库分表的基本使用 2、Sharding-JDBC分库分表之SpringBoot分片策略 3、Sharding-JDBC分库分表之SpringBoot主从配置 4、SpringBoot集成Sharding-JDBC-5.3.0分库分表 5、SpringBoot集成Sharding-JDBC-5.3.0实现按月动态建表分表 6、【…...

Spark 之 partitons

Listing leaf files and directories 分析其并行化 org.apache.spark.util.HadoopFSUtils sc.parallelize(paths, numParallelism).mapPartitions { pathsEachPartition >val hadoopConf serializableConfiguration.valuepathsEachPartition.map { path >val leafFiles…...

使用Zerotier配置虚拟局域网,踏坑

配置虚拟局域网有多种方式&#xff0c;包括带桌面的和纯网络的。 一、带桌面的&#xff08;不是本次重点&#xff09; 常见工具&#xff1a;向日葵、todesk、anydesk、restDesk 前两者是常见商业工具&#xff0c;anydesk好像很轻&#xff0c;restDesk是开源项目&#xff0c;…...

【优选算法 二分查找】二分查找算法模板详解:二分查找 & 在排序数组中查找元素的第一个和最后一个位置

二分查找 题目描述 题目解析 暴力解法 我们可以从左往右遍历一次数组&#xff0c;如果存在 target 则返回数组的下标&#xff0c;否则返回 -1&#xff1b; 时间复杂度 O(N)&#xff0c;因为没有利用数组有序的特点&#xff0c;每次比较只能舍弃一个要比较的数&…...

gitlab 生成并设置 ssh key

一、介绍 &#x1f3af; 本文主要介绍 SSH Key 的生成方法&#xff0c;以及如何在GitLab上添加SSH Key。GitLab 使用SSH协议与Git 进行安全通信。当您使用 SSH密钥 对 GitLab远程服务器进行身份验证时&#xff0c;您不需要每次都提供您的用户名和密码。SSH使用两个密钥&#x…...

计算机视觉在科学研究(数字化)中的实际应用

计算机视觉是一种利用计算机技术来解析和理解图像和视频的方法。.随着计算机技术的不断发展&#xff0c;计算机视觉被广泛应用于科学研究领域&#xff0c;为科学家提供了无限的可能。 一、生命科学领域 在生命科学领域&#xff0c;计算机视觉被广泛用于图像识别、分类和测量等…...

移动应用开发课程第六次实验:为实验2添加登陆页面,用SQList存储好友基本信息

1、在Android Studio中&#xff0c;请在第二次实验成果的基础上完成以下实验要求。 向右滑动 请添加登录页面。在登录页面中&#xff0c;如果用户输入的用户名和密码正确&#xff0c;则跳转至如上图所示的好友列表&#xff0c;并记录用户的登录信息&#xff0c;在用户第一次登…...

nextjs增加系统路径前缀(basePath)适配方案

在 Next.js 中&#xff0c;路由是通过文件夹结构来定义的&#xff0c;使用类似于 History 模式的 URL 结构。所以如果想通过nginx来代理一个nextjs开发的系统&#xff0c; 除非直接使用跟路径/来进行代理&#xff0c;否则代理将非常麻烦&#xff0c;这时添加basePath就非常有必…...

嵌入式蓝桥杯学习拓展 LCD翻转显示

通过配置SS和GS两个标志位&#xff0c;实现扫描方向的切换。 将lcd.c的REG_932X_Init函数进行部分修改。 将LCD_WriteReg(R1, 0x0000);修改为LCD_WriteReg(R1,0x0100); 将LCD_WriteReg(R96, 0x2700); 修改为LCD_WriteReg(R96, 0xA700); void REG_932X_Init1(void) {LCD_Wr…...

学习threejs,实现配合使用WebWorker

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️WebWorker web端多线程 二、…...

TDengine 新功能 复合主键

1. 简介 从 TDengine 3.3.0.0 版本之后&#xff0c;新增了复合主键的功能。 TDengine 原来的时间列是不允许有重复时间戳的&#xff0c;有了复合主键功能后&#xff0c;时间列即允许有重复&#xff0c;重复后的时间戳按紧跟其后第二列主键列的值来确定唯一性。 此功能的常用…...

JVM 面试题

Java 虚拟机&#xff08;JVM&#xff09;是运行 Java 程序的引擎&#xff0c;它是 Java 语言 “一次编译&#xff0c;处处运行” 的核心技术。JVM 的主要任务是将 Java 字节码&#xff08;Bytecode&#xff09;解释成机器码并执行&#xff0c;负责内存管理、线程管理、垃圾回收…...

组件上传图片不回显问题

import { Plus } from "element-plus/icons-vue"; // 图片上传 const img_add ref([]); function httpRequest_add(option) {let dataForm new FormData();dataForm.append("file", option.file);dataForm.append("id", user.data.id);axios({…...

【JavaWeb后端学习笔记】Spring AOP面向切面编程

AOP 1、Spring AOP概述2、SpringAOP快速入门3、SpringAOP核心概念4、通知类型5、通知顺序6、切入点表达式6.1 execution方式6.2 annotation方式 7、连接点 1、Spring AOP概述 AOP&#xff1a;Aspect Oriented Programming&#xff0c;面向特定方法编程。 AOP是通过动态代理技术…...

6.584-Lab5B

6.584-Lab5B Reference CodeReference BlogHomeworkMyself Code Sharded Key/Value Service 梗概 这个图是我从上面参考blog中拿来的&#xff0c;觉得做的不错&#xff0c;借助这张图来讲解一下需要一个什么样的 Service。 ShardCtrler Client&#xff1a; 接收来自客户发出的命…...

OceanBase 的探索与实践

作者&#xff1a;来自 vivo 互联网数据库团队- Xu Shaohui 本文总结了目前我们遇到的痛点问题并通过 OceanBase 的技术方案解决了这些痛点问题&#xff0c;完整的描述了 OceanBase 的实施落地&#xff0c;通过迁移到 OceanBase 实践案例中遇到的问题与解决方案让大家能更好的了…...

安卓调试环境搭建

前言 前段时间电脑重装了系统&#xff0c;最近准备调试一个apk&#xff0c;没想到装环境的过程并不顺利&#xff0c;很让人火大&#xff0c;于是记录一下。 反编译工具下载 下载apktool.bat和apktool.jar 官网地址&#xff1a;https://ibotpeaches.github.io/Apktool/install…...

动画Lottie

Lottie简介 Lottie是一个Airbnb 开发的用于Android&#xff0c;iOS&#xff0c;Web和Windows的库&#xff0c;用于解析使用Bodymovin导出为json的Adobe After Effects动画&#xff0c;并在移动设备和网络上呈现 — GitHub Lottie主要特性 After Effects 兼容性&#xff1a; …...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...