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、测试与效果

上传后的图片

在这里插入图片描述

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

在这里插入图片描述

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

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

相关文章

1.62亿元!812个项目立项!上海市2024年度“科技创新行动计划”自然科学基金项目立项

本期精选SCI&EI ●IEEE 1区TOP 计算机类&#xff08;含CCF&#xff09;&#xff1b; ●EI快刊&#xff1a;最快1周录用&#xff01; 知网(CNKI)、谷歌学术期刊 ●7天录用-检索&#xff08;100%录用&#xff09;&#xff0c;1周上线&#xff1b; 免费稿件评估 免费匹配期…

Flink安装和Flink CDC实现数据同步

一&#xff0c;Flink 和Flink CDC 1&#xff0c; Flink Apache Flink是一个框架和分布式处理引擎&#xff0c;用于对无界和有界数据流进行有状态计算。 中文文档 Apache Flink Documentation | Apache Flink 官方文档 &#xff1a;https://flink.apache.org Flink 中文社区…

VBA高级应用30例应用3在Excel中的ListObject对象:插入行和列

《VBA高级应用30例》&#xff08;版权10178985&#xff09;&#xff0c;是我推出的第十套教程&#xff0c;教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开&#xff0c;这套教程案例与理论结合&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以…

windows运行ffmpeg的脚本报错:av_ts2str、av_ts2timestr、av_err2str => E0029 C4576

问题描述 我目前的环境是&#xff1a; 编辑器&#xff1a; Microsoft Visual Studio Community 2022 (64 位) 运行的脚本是ffmpeg自带的remux样例&#xff0c;只不过我想用c语言执行这个样例。在执行的过程中报错如下图&#xff1a; C4576 后跟初始值设定项列表的带圆括…

如何利用 Python 的爬虫技术获取淘宝天猫商品的价格信息?

以下是使用 Python 的爬虫技术获取淘宝天猫商品价格信息的两种常见方法&#xff1a; 方法一&#xff1a;使用 Selenium 一、环境准备&#xff1a; 安装 selenium 库&#xff1a;在命令行中运行 pip install selenium。下载浏览器驱动&#xff1a;如 ChromeDriver&#xff08;确…

Linux系统程序设计--2. 文件I/O

文件I/O 标准C的I/O FILE结构体 下面只列出了5个成员 可以观察到&#xff0c;有些函数没有FILE类型的结构体指针例如printf主要是一些标准输出&#xff0c;因为其内部用到了stdin&#xff0c;stdout&#xff0c;stderr查找文件所在的位置:find \ -name stat.h查找头文件所…

Spark 中 RDD 的诞生:原理、操作与分区规则

Spark 的介绍与搭建&#xff1a;从理论到实践-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式之Yarn模式的原…

[2024最新] macOS 发起 Bilibili 直播(不使用 OBS)

文章目录 1、B站账号 主播认证2、开启直播3、直播设置添加素材、隐私设置指定窗口添加/删除 窗口 4、其它说明官方直播帮助中心直播工具教程 目前搜到的 macOS 直播教程都比较古早&#xff0c;大部分都使用 OBS&#xff0c;一番探索下来&#xff0c;发现目前已经不需要 OBS了&a…

内核设备树,你真的了解吗?

在嵌入式系统和内核开发中&#xff0c;设备树&#xff08;Device Tree, 简称 DT&#xff09;扮演着至关重要的角色&#xff0c;帮助系统在启动时准确识别硬件配置并匹配合适的驱动程序。虽然设备树应用广泛&#xff0c;但其结构、工作机制及应用细节却不总是被深入理解。本文将…

yelp数据集上识别潜在的热门商家

yelp数据集是研究B2C业态的一个很好的数据集&#xff0c;要识别潜在的热门商家是一个多维度的分析过程&#xff0c;涉及用户行为、商家特征和社区结构等多个因素。从yelp数据集里我们可以挖掘到下面信息有助于识别热门商家 用户评分和评论分析 评分均值: 商家的平均评分是反映其…

Mac如何将多个pdf文件归并到一个

电脑&#xff1a;MacBook Pro M1 操作方式&#xff1a; very easy 选中想要归并的所有pdf文件&#xff0c;然后 右键 -> quick actions -> Create PDF 然后就可以看到将所选pdf文件归并为一个pdf的文件了

华为eNSP实验:IP Source Guard

一&#xff1a;IP Source Guard: IP Source Guard&#xff08;简称IPSG&#xff09;是一种基于二层接口的源IP地址过滤技术&#xff0c;用于防止恶意主机伪造合法主机的IP地址进行网络攻击。以下是对IP Source Guard的详细解析&#xff1a; 基本概念&#xff1a; IP Source Gu…

API接口精准获取商品详情信息案例

在当今数字化时代&#xff0c;电子商务平台的蓬勃发展&#xff0c;使得商品信息的获取变得尤为重要。API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;作为连接前端用户界面与后端服务的桥梁&#xff0c;扮演着至关重要的角色。本文…

比流计算资源效率最高提升 1000 倍,“增量计算”新模式能否颠覆数据分析?

作者 | 关涛 云器科技CTO 数据平台领域发展 20 年&#xff0c;逐渐成为每个企业的基础设施。作为一个进入“普惠期”的领域&#xff0c;当下的架构已经完美了吗&#xff0c;主要问题和挑战是什么&#xff1f;在 2023 年 AI 跃变式爆发的大背景下&#xff0c;数据平台又该如何演…

牧神记开分9.7,2024新国漫巅峰出现了

现在国漫越来越卷了&#xff0c;卷播放量也卷评分。最近&#xff0c;b站上线不久的国漫《牧神记》开分9.7&#xff0c;口碑还是相当不错的&#xff0c;已经和《凡人修仙传》评分齐平。这部国漫仅仅播出4集&#xff0c;为什么就能获得这么高的评分呢&#xff1f;下面就一起来看看…

MeterSphere接口自动化-ForEach循环

接口自动化场景&#xff1a;一个接口根据不同的参数取值来运行测试&#xff0c;本场景中只有一个参数来去不同值。举例如下&#xff1a; https:://test.csdn/query?placementList1接口&#xff0c;测试id1,2,3时&#xff0c;断言接口返回的data数据都有返回。&#xff08;当然…

ServletContext介绍

文章目录 1、ServletContext对象介绍1_方法介绍2_用例分析 2、ServletContainerInitializer1_整体结构2_工作原理3_使用案例 3、Spring案例源码分析1_注册DispatcherServlet2_注册配置类3_SpringServletContainerInitializer 4_总结 ServletContext 表示上下文对象&#xff0c;…

聚观早报 | 比亚迪腾势D9登陆泰国;苹果 iOS 18.2 将发布

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 11月5日消息 比亚迪腾势D9登陆泰国 苹果 iOS 18.2 将发布 真我GT7 Pro防尘防水细节 小米15 Ultra最快明年登场 …

【Linux系统编程】第四十四弹---从TID到线程封装:全面掌握线程管理的核心技巧

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、tid是什么 1.1、理解库 1.2、理解tid 1.3、tid中线程局部存储 2、封装线程 2.1、基本结构 2.2、函数实现 2.3、使用…

智慧城市路面垃圾识别系统产品介绍方案

方案介绍 智慧城市中的路面垃圾识别算法通常基于深度学习框架&#xff0c;这些算法因其在速度和精度上的优势而被广泛采用。这些模型能够通过训练识别多种类型的垃圾&#xff0c;包括塑料袋、纸屑、玻璃瓶等。系统通过训练深度学习模型&#xff0c;使其能够识别并定位多种类型…