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

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-文件上传

二十三 、 文件上传 实现效果&#xff1a;用户点击上传按钮、选择上传的头像&#xff0c;确定自动上传&#xff0c;将上传的文件保存到指定的目录中&#xff0c;并重新命名&#xff0c;生成访问链接&#xff0c;返回给前端进行回显。 1、前端实现 vue3AntDesignVue实现 <tem…...

当AI遇上时尚:未来的衣橱会由机器人来打理吗?

内容概要 在当今这个快速发展的时代&#xff0c;人工智能与时尚的结合正在逐渐改写我们对衣橱管理的认知。传统的衣橱管理常常面临着空间不足、穿搭单调及库存过多等挑战&#xff0c;许多人在挑选服饰时难以做出决策。然而&#xff0c;随着技术的进步&#xff0c;智能推荐和自…...

【初阶数据结构篇】二叉树OJ题

文章目录 须知 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助吗&#xff1…...

Windows系统中Oracle VM VirtualBox的安装

一.背景 公司安排了师带徒&#xff0c;环境搭建问题一直是初级程序员头疼的事情&#xff0c;我记录一下这些基础的内容&#xff0c;方便初学者。大部分开发者的机器还是windows系统&#xff0c;所以写了怎么安装。 二.版本信息及 操作系统&#xff1a;windows11 家庭版…...

go语言使用总结(持续更新)

整理后的内容如下&#xff1a; 1. 先了解函数签名&#xff0c;再了解传入参数以及调用 函数签名是函数的声明部分&#xff0c;包括函数名、参数列表和返回值列表。理解函数签名是理解函数行为的第一步&#xff0c;尤其是在了解参数类型、参数数量和返回值类型等方面。通过了解…...

如何在Android中自定义property

在Android中创建自定义的属性&#xff08;Android property&#xff09;通常用于调试、性能调优或传递应用和系统之间的信息。 以下是如何在Android中创建和使用自定义属性的步骤&#xff1a; 1. 定义属性 在Android中&#xff0c;属性是以“属性名称属性值”形式定义的键值对…...

机器学习5_支持向量机_原问题和对偶问题——MOOC

目录 原问题与对偶问题的定义 定义该原问题的对偶问题如下 在定义了函数 的基础上&#xff0c;对偶问题如下&#xff1a; 综合原问题和对偶问题的定义得到&#xff1a; 定理一 对偶差距&#xff08;Duality Gap&#xff09; 强对偶定理&#xff08;Strong Duality Theo…...

索引的细节

目录 什么是线性 搜索算法&#xff1f; 算法&#xff1a;二进制搜索算法 二进制搜索如何工作&#xff1f; 什么是二叉排序树&#xff1f; 构建二叉排序树 什么是AVL树&#xff1f; AVL树的性能分析 什么是线性 搜索算法&#xff1f; 线性搜索是一种非常简单的搜索算法。在…...

LeetCode 540.有序数组中的单一元素

思路一&#xff1a;hash&#xff0c;键存入元素&#xff0c;值存入次数&#xff0c;然后遍历&#xff0c;不是最优解 思路二&#xff1a;二分查找 假设数组为 [1, 1, 2, 2, 3, 4, 4]&#xff0c;其中唯一出现一次的元素是 3。在一个有序数组中&#xff0c;如果没有唯一的元素&…...

【图文】【DIY便签】如何自行编译OPENCV使用动态库

1 去官网下载安装包和源码 下面红色圈中的是源码&#xff0c;绿色圈中的是安装包&#xff1a; 2 配置工具链 安装过程不说了&#xff0c;教程到处都是。编译的话使用CMAKE&#xff0c;配置如下&#xff1a; 上面两个路径分别是&#xff1a; 源码目录编译生成的文件放置的位…...

WordPress文章自动提交Bing搜索引擎:PHP推送脚本教程

随着网站SEO优化的重要性日益增加,将新发布的内容快速提交到搜索引擎显得尤为重要。尤其对于Bing站长平台,自动化推送能让Bing尽快发现和索引我们网站的新内容。本文将详细介绍如何通过PHP脚本自动推送WordPress当天发布的文章至Bing站长平台,确保新文章被Bing及时收录。 前…...

C++题目分享

嗨嗨嗨&#xff0c;我又来更新这个系列了&#xff0c;很久没更新了。让我们看一看有那些有趣的题目&#xff1a; 题目一&#xff1a; 1.以单链表作为存储结构&#xff0c;实现线性表的就地逆置&#xff08;提示&#xff0c;就地逆置&#xff1a;在不使用额外的数据结构或空间…...

【Spring 框架】初识 Spring

文章目录 前言1. 什么是 Spring2. 什么是 Maven3. 第一个 SpringBoot 项目4. 项目讲解结语 前言 在前面我们一起学习了 JavaSE 的基础知识&#xff0c;随着学习的深入&#xff0c;我们也将逐步介绍 JavaEE 的内容&#xff0c;像 Spring 框架&#xff0c;Mybatis 等等。在本篇博…...

链表(Linkedlist)

序言 我们都了解链表是一种数据的存储结构&#xff0c;在Java使用中逻辑与c&#xff0c;c语言数据结构别无二致&#xff0c;但主要由于Java中不存在指针的说法&#xff0c;从而导致在实现过程中的代码不同&#xff0c;所以在学习的过程中我们无需过于担心&#xff0c;逻辑都是…...

信息安全工程师(79)网络安全测评概况

一、定义与目的 网络安全测评是指参照一定的标准规范要求&#xff0c;通过一系列的技术、管理方法&#xff0c;获取评估对象的网络安全状况信息&#xff0c;并对其给出相应的网络安全情况综合判定。其对象主要为信息系统的组成要素或信息系统自身。网络安全测评的目的是为了提高…...

保研考研机试攻略:python笔记(3)

&#x1f428;&#x1f428;&#x1f428;11sort 与 sorted 区别 sort 是应用在 list 上的方法&#xff0c;sorted 可以对所有可迭代的对象进行排序操作。 list 的 sort 方法返回的是对已经存在的列表进行操作&#xff0c; 无返回值&#xff0c;而内建函数 sorted 方法返回的…...

刘卫国MATLAB程序设计与应用课后答案PDF第三版

刘卫国《MATLAB程序设计与应用》&#xff08;第三版&#xff09;是对普通高等教育“十一五”国家级规划教材《MATLAB程序设计与应用》(第二版)的一次全面修订。全书总体保持第二版原有体系结构&#xff0c;但根据技术发展和应用的需要扩充了许多新内容。全书强调数学方法、算法…...

【鉴权】Web 会话管理:Cookie、Session 和 Token 深度对比

目录 引言一、Cookie二、Session三、Token (JWT)四、总结对比五、Token、Session 和 Cookie 的选择总结 引言 在现代 Web 开发中&#xff0c;Cookie、Session 和 Token 都是用于用户身份验证和状态管理的常见技术。每种技术有其特定的应用场景和优缺点&#xff0c;理解它们之间…...

ArkTS--应用状态

应用状态 应用状态相关的内容需要使用模拟器或真机调试&#xff0c;在API 11开始也支持preview 1.LocalStorage LocalStorage是页面级的UI状态存储&#xff0c;通过Entry装饰器接收参数可以在页面内共享数据 1.1 页面内共享数据 import {MyUser} from ../model/MyUser //用户对…...

yolov8涨点系列之引入CBAM注意力机制

文章目录 YOLOv8 中添加注意力机制 CBAM 具有多方面的好处特征增强与选择通道注意力方面空间注意力方面 提高模型性能计算效率优化&#xff1a; yolov8增加CBAM具体步骤CBAM代码(1)在__init.pyconv.py文件的__all__内添加‘CBAM’(2)conv.py文件复制粘贴CBAM代码(3)修改task.py…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天&#xff0c;深度学习与大模型技术已成为推动行业变革的核心驱动力&#xff0c;而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心&#xff0c;系统性地呈现了两部深度技术著作的精华&#xff1a;…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter

java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用&#xff08;Math::max&#xff09; 2 函数接口…...

WEB3全栈开发——面试专业技能点P4数据库

一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库&#xff0c;基于 mysql 库改进而来&#xff0c;具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点&#xff1a; 支持 Promise / async-await&#xf…...

职坐标物联网全栈开发全流程解析

物联网全栈开发涵盖从物理设备到上层应用的完整技术链路&#xff0c;其核心流程可归纳为四大模块&#xff1a;感知层数据采集、网络层协议交互、平台层资源管理及应用层功能实现。每个模块的技术选型与实现方式直接影响系统性能与扩展性&#xff0c;例如传感器选型需平衡精度与…...

MLP实战二:MLP 实现图像数字多分类

任务 实战&#xff08;二&#xff09;&#xff1a;MLP 实现图像多分类 基于 mnist 数据集&#xff0c;建立 mlp 模型&#xff0c;实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入&#xff0c;可视化图形数字&#xff1b; 2、完成数据预处理&#xff1a;图像数据维度转换与…...