Spring Boot中保存前端上传的图片

article/2025/6/23 16:14:46

在Spring Boot中保存前端上传的图片可以通过以下步骤实现:

1. 添加依赖

确保在pom.xml中已包含Spring Web依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. 配置文件上传限制

application.properties中设置文件大小限制:

spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
#====自定义变量======
#文件上传地址
file.upload.dir=uploads/

3. 创建文件上传控制器

package com.hirain.mall.controller;import com.hirain.mall.common.ApiRestResponse;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.UUID;@RestController
@RequestMapping("/images")
public class ImageController {@Value("${file.upload.dir}") // 从配置文件中读取路径private String uploadDir;@PostMapping("/upload")public ApiRestResponse<?> uploadImage(@RequestParam("image") MultipartFile file,HttpServletRequest request) {try {// 创建目录 (如果不存在)Path uploadPath = Paths.get(uploadDir);if (!Files.exists(uploadPath)) {Files.createDirectories(uploadPath);}// 生成唯一文件名 (避免覆盖)String originalFileName = file.getOriginalFilename();String fileExt = originalFileName.substring(originalFileName.lastIndexOf("."));String newFileName = UUID.randomUUID() + fileExt;// 保存文件Path targetPath = uploadPath.resolve(newFileName);Files.copy(file.getInputStream(), targetPath);// 生成访问 URL (使用环境信息构建完整URL)String baseUrl = request.getRequestURL().toString().replace(request.getRequestURI(), "");String imageUrl = baseUrl + "/images/" + newFileName;return ApiRestResponse.success(Map.of("filename", newFileName,"url", imageUrl//完成静态资源映射配置后,通过浏览器直接访问该地址即可访问图片));} catch (Exception e) {return ApiRestResponse.error(500,"上传失败: " + e.getMessage());}}
}

4.静态资源映射配置类WebConfig

package com.hirain.mall.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.io.File;@Configuration
public class WebConfig implements WebMvcConfigurer {@Value("${file.upload.dir}")private String uploadDir;@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 将真实的上传目录映射为虚拟路径registry.addResourceHandler("/images/**").addResourceLocations("file:" + uploadDir + File.separator);}
}

5. 前端调用示例(HTML)

<input type="file" id="imageInput">
<button onclick="uploadImage()">上传</button><script>
async function uploadImage() {const fileInput = document.getElementById('imageInput');const formData = new FormData();formData.append('image', fileInput.files[0]);const response = await fetch('http://localhost:8080/images/upload', {method: 'POST',body: formData});const result = await response.text();console.log(result);
}
</script>

6. postman调用示例

在这里插入图片描述

关键点说明:

  1. 文件保存路径

    • 示例中使用相对路径uploads/(项目根目录下)
    • 生产环境建议使用绝对路径(如/var/www/uploads/
  2. 文件名处理

    • 使用时间戳前缀确保唯一性
    • 保留原始文件名后缀(通过file.getOriginalFilename()获取)
  3. 异常处理

    • 捕获IOException处理文件操作异常
    • 返回错误信息给前端

进阶优化建议:

  1. 添加文件类型校验

    if (!file.getContentType().startsWith("image/")) {return "仅支持图片文件";
    }
    
  2. 添加安全限制

    • 限制文件扩展名(jpg, png等)
    • 使用病毒扫描工具扫描上传文件
  3. 云存储方案

    • 生产环境建议使用云存储(AWS S3, 阿里云OSS等)
    • 示例代码替换为云存储SDK的上传逻辑

处理流程示意图:

在这里插入图片描述
其中,前端上传图片后,后端保存在本地的流程如下:

前端 → 发送Multipart请求 → Spring控制器 → 验证文件 → 生成唯一文件名 → 保存到本地 → 返回结果

根据实际需求选择本地存储或云存储方案,并注意做好文件类型校验和安全防护措施。


http://www.hkcw.cn/article/cgDUfxSMuG.shtml

相关文章

并查集(上)

1 并查集所包含的方法 int find(a); bool issameset(a,b); void union(a,b); 方法一&#xff1a;int find(a);这个表示是否可以找到这里集合的代表元素 方法二&#xff1a; bool issameset(a,b);这个是表示两个元素是否在一个集合 方法三&#xff1a;void union(a,b);这个表示…

「完整」AI文档库 | 5月20最新发布,221页,《北京大学AI+Agent与Agentic+AI的原理和应用洞察与未来展望》

昨天大师兄给大家介绍了复旦大学的一篇关于AI的讲座。 「完整」AI文档库 | 终于等到你&#xff0c;《复旦大学&#xff1a;大语言模型能力来源与边界》 今天大师兄给大家带来一篇《北京大学DeepSeek系列11&#xff1a;AIAgent与AgenticAI的原理和应用洞察与未来展望》。这篇A…

《棒球万事通》棒球特长生升学方向·棒球1号位

棒球升学双轨制发展路径解析/Bilingual Baseball Career Pathway Analysis 1. 美国大学体育奖学金体系/US Collegiate Scholarship System 核心数据: NCAA D1院校平均每年提供11.7个棒球奖学金 顶级投手球速标准: 高中毕业前需达87-95mph(约140-153km/h) 学术基准: NCAA要…

使用nhdeep档案管理系统单机版,创建归档文件目录打印文件

打开nhdeep档案管理系统单机版&#xff0c;查看已经导入或添加到文书档案库管理的条目数据。 文书档案库件目录信息&#xff1a; 文书档案库盒信息&#xff1a; 选择多条盒记录&#xff0c;点击盒内目录打印按钮&#xff0c;打开预览窗口 可以选择归档文件的打印模版&#xff…

2022年第十三届蓝桥杯青少c++省赛真题——分解整数

2022年第十三届蓝桥杯青少c省赛真题——分解整数 题目点下方&#xff0c;支持在编程&#xff0c;在线测评~ 分解整数_C_少儿编程题库学习中心-嗨信奥 题库收集了历届各白名单赛事真题和权威机构考级真题&#xff0c;覆盖初赛—省赛—国赛&#xff0c;支持在线考试&#xff0c;…

CUDA与OpenGL混合编程图形渲染

CUDA与OpenGL混合编程图形渲染 CUDA与OpenGL混合编程图形渲染 CUDA与OpenGL混合编程图形渲染前言一、 通过OpenGL映射GPU内存二、CUDA使用的两种OpenGL内存对象1、像素缓冲对象&#xff08;PBO&#xff09;&#xff1a;OpenGL中用于存储像素的一段内存。2D图像是由多个像素和颜…

俄乌第二轮谈判都谈了哪些内容 换俘与停火提议成焦点

6月2日,俄罗斯和乌克兰两国代表团在土耳其伊斯坦布尔就和平解决俄乌冲突举行第二轮直接谈判。会谈结束后,俄方代表团团长、俄总统助理梅金斯基表示,俄方对第二轮谈判的成果感到满意。梅金斯基透露,俄方向乌方提交了关于乌克兰问题的和平备忘录,其中包含实现真正停火的建议…

乒超联赛门票于6月3日开售 雄安新区首迎顶尖赛事

6月9日至11日,2025赛季中国乒乓球俱乐部超级联赛常规赛第一阶段比赛将在河北雄安新区雄安体育中心体育馆举行。赛事门票将于6月3日18:00在秀动票务平台开售,票价从288元至788元不等。2025赛季乒超联赛包括男子和女子团体赛,分为三个阶段的常规赛和总决赛,时间跨度从6月到12…

女子拖欠停车费近3000元被起诉:怎么证明是我的车在停放

多次把车停在路边收费停车位上却不交费,两年半拖欠了近3000元停车费,常德女子李倩(化名)被起诉到法院。对此李倩称,收费公司使用的感应、计费系统常出故障,无法证明收费时段是她的车在停放,请求法院驳回起诉。6月2日,记者从中国裁判文书网获悉,常德中院判决李倩须支付…

小伙被4根烧烤签扎进脖子 已脱离生命危险

6月2日凌晨2时许,有网友发帖称山西临汾一名小伙脖子上被扎了多根烧烤签。视频显示,小伙脖子上插着四根金属签子,签上还有烧烤肉串,急救人员小心翼翼地将他送往病床。据了解,事发凌晨零时前后,一家烧烤店内两名年轻人发生口角,一人扔出烧烤签时不慎将其扎进另一人的脖子。…

香港一银行遭劫匪抢走30余万港币 职员受伤已出院

6月2日,香港恒生银行沙田第一城分行发生一起持刀抢劫案。一名劫匪持刀威胁银行职员后劫走约30余万元港币及少量外币,随后逃离现场。案件中有一名职员颈部受轻伤,送往医院救治后已出院。当天17时许,警方接到报案称,一名男子独自进入银行,坐下约15分钟后突然拿出一把刀,威…

谁有望成为韩国新总统 李在明领跑选情

韩国第21届总统选举定于6月3日举行,主要候选人仍在抓紧最后机会展开竞选活动,争取更多选票。此次大选在前总统尹锡悦被弹劾之后举行,共有7名候选人登记参选,但其中两人已宣布退选,最终有5名候选人参加大选角逐。这5名候选人分别是共同民主党候选人李在明、国民力量党候选人…

连贾冰都瘦了!就等一个沈腾了 喜剧圈瘦身潮来袭

沙溢、贾玲、贾冰都瘦了,压力给到了沈腾。今天,话题“贾冰减肥成功瘦到脱相”登上微博热搜。起因是5月31日,演员贾冰的妻子发视频祝福大家端午节快乐,并配文“从此我家多了个瘦子”。从贾冰妻子发布的两人合影中可以看到,贾冰明显瘦了很多。评论区纷纷询问他怎么瘦了这么多…

韩大选正式投票 五候选人角逐总统

韩国第21届总统选举于当地时间3日6时在全国14295个投票站正式启动,投票截止时间为当晚8时。5月29日上午6时,韩国进行了“事前投票”,选民在首尔麻浦区等地的投票站等候投票。预计选举结果最早可于3日晚12时左右初现轮廓。新任总统将面临经济、政治等多重考验,并需缓解保守和…

欧洲最高的活火山喷发 数千米高羽流壮观景象

6月2日,意大利西西里岛的埃特纳火山发生大规模喷发,形成了数千米高的火山羽流。据社交媒体上的目击者称,远在50公里外的陶尔米纳和40公里外的卡塔尼亚都能听到爆炸声。西西里岛民防部门发布航空通知,要求所有航班避开该地区。埃特纳火山海拔超过3300米,有多个火山口,是欧…

大乐透开出10注一等奖!单注超800万 奖金高达814万

大皖新闻讯 6月2日,中国体彩网更新了彩票开奖公告。其中,超级大乐透开出10注一等奖,单注奖金8139831元。具体如下:编辑 汪艳责任编辑:zx0176

Docker 在电商场景中的应用:从 Java 应用到数据库的容器化改造(以 MySQL/Redis 为例演示容器化部署)

在电商领域,面对瞬息万变的市场需求、海量的并发流量以及复杂多样的业务逻辑,系统的稳定性、可伸缩性和快速迭代能力显得尤为重要。传统的应用部署方式往往伴随着环境不一致、依赖管理复杂、资源隔离性差等痛点。此时,Docker 容器化技术 应运而生,为电商平台的构建和运维带…

学习BI---基本操作---数据集操作

什么是数据集&#xff0c; 数据集&#xff08;Dataset&#xff09;​​ 是指从原始数据源&#xff08;如数据库、Excel、API等&#xff09;提取并经过标准化处理后的数据集合&#xff0c;通常以二维表形式存储&#xff0c;用于支撑报表、仪表盘等可视化分析。 数据集在QuickB…

【入门】【练9.3】 加四密码

| 时间限制&#xff1a;C/C 1000MS&#xff0c;其他语言 2000MS 内存限制&#xff1a;C/C 64MB&#xff0c;其他语言 128MB 难度&#xff1a;中等 分数&#xff1a;100 OI排行榜得分&#xff1a;12(0.1*分数2*难度) 出题人&#xff1a;root | 描述 要将 China…

马思纯聚餐结束后在停车场等男友 甜蜜等待羡煞旁人

马思纯聚餐结束后在停车场等男友 甜蜜等待羡煞旁人!嘿,宝子们!这娱乐圈的瓜田里又长出一颗超甜的瓜!马思纯和张哲轩的感情生活最近又让大家狠狠吃了一把糖。你有没有想过,为什么他们的感情能一直这么稳定又甜蜜呢?马思纯和朋友们聚餐结束后,在停车场耐心等男友张哲轩。她…