JavaWeb合集23-文件上传
二十三 、 文件上传
实现效果:用户点击上传按钮、选择上传的头像,确定自动上传,将上传的文件保存到指定的目录中,并重新命名,生成访问链接,返回给前端进行回显。
1、前端实现
vue3+AntDesignVue实现
<template><!--图片回显--><a-avatar :size="100"><template #icon><img :src="userStore.userInfo.avatar+'?' + new Date().getTime()" alt=""></template></a-avatar><!--图片上传按钮 --><!--showUploadList=fales 不显示上传列表;:multiple="false" 只上传1个;accept=".png,.jpg" 限制文件格式--><a-upload name="file":file-list="fileList":showUploadList="false":beforeUpload="beforeUpload" :onChange="handleChange" :multiple="false" accept=".png,.jpg"><a-button class="mt-4">上传头像</a-button></a-upload></template><script setup lang="ts">
import type { UnwrapRef } from 'vue';
import { updateUserAvatarApi } from '~/api/file/file.ts';const { t } = useI18n()
//文件列表
const fileList = ref([]);//
async function beforeUpload(file){//文件类型,限制,可以不用写,因为,在accept=".png,.jpg" 已经限制了
var fileName = file.name.substring(file.name.lastIndexOf('.') + 1)
if (fileName!='png' && fileName!='jpg') {message.error('文件类型必须是png或jpg!')
return false
}//文件大小(3M=3*1024KB*1024字节)
var fileSize=file.size;
if(fileSize > 3*1024*1024){message.error("图片大小不能大于3M");return false
}try { const formData = new FormData(); formData.append('file', file); // 将文件添加到 FormData 对象中 // 假设updateUserAvatarApi返回的是一个Promise,且解析为包含fileUrl的对象 const response = await updateUserAvatarApi(formData); if(response.data.code==1){fileList.value=[]; //清空文件列表(没用因为在beforeUpload中,我直接showUploadList="false"不显示列表)userStore.userInfo.avatar=response.data.data;message.success('头像上传成功');}else{message.error('头像上传失败,请重试'); }} catch (error) { // 处理上传失败的情况 message.error(error); } // 返回false以阻止<a-upload>的默认上传行为 return false; }// 处理文件上传或移除后的逻辑
function handleChange(info) { // info.fileList 是更新后的文件列表 // 但由于限制了multiple为false,所以这里fileList应该始终只有一个文件或为空 fileList.value = info.fileList.slice(-1);
} </script>
请求函数
// 后面的方法是用户自己头像
export function updateUserAvatarApi(param: any) {return usePost<FileUrl>('/upload/uploadUserAvater', param, {// 设置为false的时候不会携带tokentoken: true,// 开发模式下使用自定义的接口customDev: true,// 是否开启全局请求loadingloading: false,// 设置请求头headers: {'Content-Type': 'multipart/form-data'}})}export interface FileUrl {data: string}
2、后端实现
配置拦截器的静态资源映射,方便对上传后的文件进行访问
/*** 配置拦截器的静态资源映射*/
@Slf4j
@Configuration
public class ResourConfigure implements WebMvcConfigurer {// 静态资源映射@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {/*** 资源映射路径* addResourceHandler:访问映射路径* addResourceLocations:资源绝对路径*/String osName=System.getProperty("os.name");String fileUploadResources="/static/**";String win="win";if(osName.toLowerCase().startsWith(win)){ApplicationHome applicationHome=new ApplicationHome(this.getClass());String pre="file:"+applicationHome.getDir().getParentFile().getParentFile()+ "\\src\\main\\resources\\static\\";registry.addResourceHandler(fileUploadResources).addResourceLocations(pre);}else {ApplicationHome applicationHome=new ApplicationHome(this.getClass());String pre="file:"+applicationHome.getDir().getParentFile().getParentFile()+ "/src/main/resources/static/";registry.addResourceHandler(fileUploadResources).addResourceLocations(pre);}}}
写相关配置,在application.properties中,方便生成访问链接
#根据自己的需求进行修改即可
#端口号
server.port=8080
#服务地址
server.address=localhost
#访问路径
server.servlet.context-path=/
#限制单个文件的上传大小
spring.servlet.multipart.max-file-size=5MB
#限制整个请求的最大大小
spring.servlet.multipart.max-request-size=5MB
创建文件上传工具类,方便对文件上传进行操作。
在此之前,确保这个目录的存在:(\src\main\resources\static\)可根据自己需求进行修改,在工具类中
/*** 文件上传工具类*/
@Component
public class FileUpload {@Value("${server.servlet.context-path}")private String contextPath;@Value("${server.port}")private String serverPort;@Value("${server.address}")private String serverAddress;@Autowiredprivate ServletContext servletContext;public String uploadFile(MultipartFile file, String folder) {// 获取图片的原始名字String originalFilename = file.getOriginalFilename();if (originalFilename == null || originalFilename.isEmpty()) {throw new IllegalArgumentException("文件名不能为空");}// 获取文件的后缀和新文件名String ext = "." + originalFilename.substring(originalFilename.lastIndexOf('.') + 1);String uuid = UUID.randomUUID().toString().replace("-", "");String fileName = uuid + ext;// 构建目标文件路径String pre = getResourcePath(folder);String filePath = pre + fileName;// 上传图片try {file.transferTo(new File(filePath));// 返回访问链接return getAccessPath(folder, fileName);} catch (IOException e) {e.printStackTrace();}return null;}public String uploadFile(MultipartFile file, String folder, String fileName) {// 获取图片的原始名字String originalFilename = file.getOriginalFilename();if (originalFilename == null || originalFilename.isEmpty()) {throw new IllegalArgumentException("文件名不能为空");}// 获取文件的后缀和新文件名String ext = "." + originalFilename.substring(originalFilename.lastIndexOf('.') + 1);fileName = fileName + ext;// 构建目标文件路径String pre = getResourcePath(folder);String filePath = pre + fileName;// 上传图片try {file.transferTo(new File(filePath));// 返回访问链接return getAccessPath(folder, fileName);} catch (Exception e) {e.printStackTrace();}return null;}//获取上传路径private String getResourcePath(String folder) {// 获取操作系统的名称String osName = System.getProperty("os.name");String win = "win";// 获取项目的根目录String projectRoot = System.getProperty("user.dir");// 根据操作系统生成正确的路径String staticPath;if (osName.toLowerCase().startsWith(win)) {//windos系统staticPath = projectRoot + "\\src\\main\\resources\\static\\" + folder + "\\";} else {//Linux系统staticPath = projectRoot + "/src/main/resources/static/" + folder + "/";}// 如果目录不存在,就创建目录File dir = new File(staticPath);if (!dir.exists()) {dir.mkdirs();}return staticPath;}//构建访问路径private String getAccessPath(String folder, String fileName) {// 构建访问路径return "http://" + serverAddress + ":" + serverPort + contextPath + "static/" + folder + "/" + fileName;}
}
可以设置一个常量类,来指定上传到的目录
public class FileUploadFolder {public static final String USER_AVATER_FOLDER = "user_avatar";public static final String ACTIVITY_FOLDER = "activity";
}
后端接口编写:Controller层,根据自己的项目来即可
@Tag(name="文件上传接口")
@RestController
@RequestMapping("/upload")
@Slf4j
public class UploadController {@Autowiredprivate UserService userService;/*** 修改用户头像* @param file* @return*/@Operation(summary = "修改用户头像")@PostMapping("/uploadUserAvater")public ResponseResult uploadUserAvater(@RequestParam("file") MultipartFile file){if(file.isEmpty()){return ResponseResult.error("头像为空,请重新选择");}String imgUrl = userService.uploadUserAvater(file);if(imgUrl==null){return ResponseResult.error("头像上传失败");}return ResponseResult.success(imgUrl);}}
Service层:根据自己的项目来即可
@Slf4j
@Service
@Transactional
public class UserServiceImpl implements UserService {//根据自己的项目来,注入对应的Bean@Autowiredprivate final UserMapper userMapper;//注入写好的工具类@Autowiredprivate FileUpload fileUpload;/*** 修改用户头像* @param file* @return*/@Overridepublic String uploadUserAvater(MultipartFile file) {// 获取用户获取用户信息(根据自己的项目来,获取用户ID,来查询用户修改头像链接)Long uid = Long.parseLong(StpUtil.getLoginId().toString());UserInfo userInfo = userMapper.getUserById(uid);// 调用文件上传工具类,传入:文件,保存到的文件夹,文件名//设置文件名是为了替换旧的头像文件String imgUrl= fileUpload.uploadFile(file, FileUploadFolder.USER_AVATER_FOLDER,userInfo.getUsername());if(imgUrl!=null) {userInfo.setAvatar(imgUrl);userMapper.updateById(userInfo);log.info("头像上传成功:" + imgUrl);//返回生成的链接return imgUrl;}return null;}}
3、测试与效果
上传后的图片

生成的访问链接,存入到数据库的样子

相关文章:
JavaWeb合集23-文件上传
二十三 、 文件上传 实现效果:用户点击上传按钮、选择上传的头像,确定自动上传,将上传的文件保存到指定的目录中,并重新命名,生成访问链接,返回给前端进行回显。 1、前端实现 vue3AntDesignVue实现 <tem…...
当AI遇上时尚:未来的衣橱会由机器人来打理吗?
内容概要 在当今这个快速发展的时代,人工智能与时尚的结合正在逐渐改写我们对衣橱管理的认知。传统的衣橱管理常常面临着空间不足、穿搭单调及库存过多等挑战,许多人在挑选服饰时难以做出决策。然而,随着技术的进步,智能推荐和自…...
【初阶数据结构篇】二叉树OJ题
文章目录 须知 💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力! 👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗࿱…...
Windows系统中Oracle VM VirtualBox的安装
一.背景 公司安排了师带徒,环境搭建问题一直是初级程序员头疼的事情,我记录一下这些基础的内容,方便初学者。大部分开发者的机器还是windows系统,所以写了怎么安装。 二.版本信息及 操作系统:windows11 家庭版…...
go语言使用总结(持续更新)
整理后的内容如下: 1. 先了解函数签名,再了解传入参数以及调用 函数签名是函数的声明部分,包括函数名、参数列表和返回值列表。理解函数签名是理解函数行为的第一步,尤其是在了解参数类型、参数数量和返回值类型等方面。通过了解…...
如何在Android中自定义property
在Android中创建自定义的属性(Android property)通常用于调试、性能调优或传递应用和系统之间的信息。 以下是如何在Android中创建和使用自定义属性的步骤: 1. 定义属性 在Android中,属性是以“属性名称属性值”形式定义的键值对…...
机器学习5_支持向量机_原问题和对偶问题——MOOC
目录 原问题与对偶问题的定义 定义该原问题的对偶问题如下 在定义了函数 的基础上,对偶问题如下: 综合原问题和对偶问题的定义得到: 定理一 对偶差距(Duality Gap) 强对偶定理(Strong Duality Theo…...
索引的细节
目录 什么是线性 搜索算法? 算法:二进制搜索算法 二进制搜索如何工作? 什么是二叉排序树? 构建二叉排序树 什么是AVL树? AVL树的性能分析 什么是线性 搜索算法? 线性搜索是一种非常简单的搜索算法。在…...
LeetCode 540.有序数组中的单一元素
思路一:hash,键存入元素,值存入次数,然后遍历,不是最优解 思路二:二分查找 假设数组为 [1, 1, 2, 2, 3, 4, 4],其中唯一出现一次的元素是 3。在一个有序数组中,如果没有唯一的元素&…...
【图文】【DIY便签】如何自行编译OPENCV使用动态库
1 去官网下载安装包和源码 下面红色圈中的是源码,绿色圈中的是安装包: 2 配置工具链 安装过程不说了,教程到处都是。编译的话使用CMAKE,配置如下: 上面两个路径分别是: 源码目录编译生成的文件放置的位…...
WordPress文章自动提交Bing搜索引擎:PHP推送脚本教程
随着网站SEO优化的重要性日益增加,将新发布的内容快速提交到搜索引擎显得尤为重要。尤其对于Bing站长平台,自动化推送能让Bing尽快发现和索引我们网站的新内容。本文将详细介绍如何通过PHP脚本自动推送WordPress当天发布的文章至Bing站长平台,确保新文章被Bing及时收录。 前…...
C++题目分享
嗨嗨嗨,我又来更新这个系列了,很久没更新了。让我们看一看有那些有趣的题目: 题目一: 1.以单链表作为存储结构,实现线性表的就地逆置(提示,就地逆置:在不使用额外的数据结构或空间…...
【Spring 框架】初识 Spring
文章目录 前言1. 什么是 Spring2. 什么是 Maven3. 第一个 SpringBoot 项目4. 项目讲解结语 前言 在前面我们一起学习了 JavaSE 的基础知识,随着学习的深入,我们也将逐步介绍 JavaEE 的内容,像 Spring 框架,Mybatis 等等。在本篇博…...
链表(Linkedlist)
序言 我们都了解链表是一种数据的存储结构,在Java使用中逻辑与c,c语言数据结构别无二致,但主要由于Java中不存在指针的说法,从而导致在实现过程中的代码不同,所以在学习的过程中我们无需过于担心,逻辑都是…...
信息安全工程师(79)网络安全测评概况
一、定义与目的 网络安全测评是指参照一定的标准规范要求,通过一系列的技术、管理方法,获取评估对象的网络安全状况信息,并对其给出相应的网络安全情况综合判定。其对象主要为信息系统的组成要素或信息系统自身。网络安全测评的目的是为了提高…...
保研考研机试攻略:python笔记(3)
🐨🐨🐨11sort 与 sorted 区别 sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。 list 的 sort 方法返回的是对已经存在的列表进行操作, 无返回值,而内建函数 sorted 方法返回的…...
刘卫国MATLAB程序设计与应用课后答案PDF第三版
刘卫国《MATLAB程序设计与应用》(第三版)是对普通高等教育“十一五”国家级规划教材《MATLAB程序设计与应用》(第二版)的一次全面修订。全书总体保持第二版原有体系结构,但根据技术发展和应用的需要扩充了许多新内容。全书强调数学方法、算法…...
【鉴权】Web 会话管理:Cookie、Session 和 Token 深度对比
目录 引言一、Cookie二、Session三、Token (JWT)四、总结对比五、Token、Session 和 Cookie 的选择总结 引言 在现代 Web 开发中,Cookie、Session 和 Token 都是用于用户身份验证和状态管理的常见技术。每种技术有其特定的应用场景和优缺点,理解它们之间…...
ArkTS--应用状态
应用状态 应用状态相关的内容需要使用模拟器或真机调试,在API 11开始也支持preview 1.LocalStorage LocalStorage是页面级的UI状态存储,通过Entry装饰器接收参数可以在页面内共享数据 1.1 页面内共享数据 import {MyUser} from ../model/MyUser //用户对…...
yolov8涨点系列之引入CBAM注意力机制
文章目录 YOLOv8 中添加注意力机制 CBAM 具有多方面的好处特征增强与选择通道注意力方面空间注意力方面 提高模型性能计算效率优化: yolov8增加CBAM具体步骤CBAM代码(1)在__init.pyconv.py文件的__all__内添加‘CBAM’(2)conv.py文件复制粘贴CBAM代码(3)修改task.py…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...
LangChain【6】之输出解析器:结构化LLM响应的关键工具
文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器?1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...
二叉树-144.二叉树的前序遍历-力扣(LeetCode)
一、题目解析 对于递归方法的前序遍历十分简单,但对于一位合格的程序猿而言,需要掌握将递归转化为非递归的能力,毕竟递归调用的时候会调用大量的栈帧,存在栈溢出风险。 二、算法原理 递归调用本质是系统建立栈帧,而非…...
智警杯备赛--excel模块
数据透视与图表制作 创建步骤 创建 1.在Excel的插入或者数据标签页下找到数据透视表的按钮 2.将数据放进“请选择单元格区域“中,点击确定 这是最终结果,但是由于环境启不了,这里用的是自己的excel,真实的环境中的excel根据实训…...
