Spring Boot项目中实现文件的上传、下载和预览功能
在Spring Boot项目中实现文件的上传、下载和预览功能,可以通过使用Spring MVC的MultipartFile接口来处理文件上传,并使用HttpServletResponse或Resource来实现文件下载和预览。下面是如何实现这些功能的完整示例。
1. 引入依赖
确保在pom.xml中引入了Spring Boot的相关依赖。通常情况下,Spring Boot Starter Web已经包含了必要的依赖。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
2. 创建文件上传、下载和预览的Controller
你可以创建一个FileController来处理文件的上传、下载和预览。
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;@Controller
@RequestMapping("/files")
public class FileController {// 文件保存路径(可以通过配置文件进行配置)@Value("${file.upload-dir}")private String fileUploadDir;// 文件上传@PostMapping("/upload")@ResponseBodypublic String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {// 获取文件名并且保存文件String fileName = file.getOriginalFilename();Path targetLocation = Paths.get(fileUploadDir).resolve(fileName);Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);// 返回文件下载的URLString fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath().path("/files/download/").path(fileName).toUriString();return "File uploaded successfully: " + fileDownloadUri;}// 文件下载@GetMapping("/download/{fileName}")public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) throws MalformedURLException {Path filePath = Paths.get(fileUploadDir).resolve(fileName).normalize();Resource resource = new UrlResource(filePath.toUri());if (!resource.exists()) {return ResponseEntity.notFound().build();}return ResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM).header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"").body(resource);}// 文件预览(主要针对图片、PDF等可以直接在浏览器中显示的文件)@GetMapping("/preview/{fileName}")public ResponseEntity<Resource> previewFile(@PathVariable String fileName) throws MalformedURLException {Path filePath = Paths.get(fileUploadDir).resolve(fileName).normalize();Resource resource = new UrlResource(filePath.toUri());if (!resource.exists()) {return ResponseEntity.notFound().build();}String contentType = "application/octet-stream";try {contentType = Files.probeContentType(filePath);} catch (IOException e) {e.printStackTrace();}return ResponseEntity.ok().contentType(MediaType.parseMediaType(contentType)).body(resource);}
}
3. 配置文件上传目录
在application.properties或application.yml中配置文件的上传路径:
file.upload-dir=C:/uploads
或者使用application.yml:
file:upload-dir: C:/uploads
你可以将路径配置为你项目的目录,也可以指定到服务器的某个位置。
4. 创建上传目录
确保在你的系统上已经创建了配置文件中指定的上传目录,比如C:/uploads。如果没有创建,可以通过代码在项目启动时自动创建:
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;@Component
public class FileUploadDirectoryInitializer implements CommandLineRunner {@Value("${file.upload-dir}")private String fileUploadDir;@Overridepublic void run(String... args) throws Exception {Path uploadPath = Paths.get(fileUploadDir);if (!Files.exists(uploadPath)) {Files.createDirectories(uploadPath);}}
}
5. 测试上传、下载和预览
5.1 文件上传
你可以使用Postman、cURL或者前端页面来测试文件上传功能。上传文件的URL为:
POST http://localhost:8080/files/upload
参数名称为file。
5.2 文件下载
你可以通过以下URL下载文件:
GET http://localhost:8080/files/download/{fileName}
其中{fileName}是文件的名称。
5.3 文件预览
你可以通过以下URL预览文件(如图片或PDF):
GET http://localhost:8080/files/preview/{fileName}
6. 处理大文件上传
对于大文件上传,Spring Boot默认的最大上传文件大小可能不满足需求,可以通过以下配置进行调整:
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB
或者在application.yml中:
spring:servlet:multipart:max-file-size: 100MBmax-request-size: 100MB
7. 文件预览类型支持
通常情况下,浏览器支持预览的文件类型包括图片(如jpeg、png)、PDF、文本文件等。如果文件类型不被浏览器支持,通常可以通过文件下载的方式处理。
8. 文件删除功能(可选)
你也可以添加一个删除文件的接口,来删除已上传的文件:
// 文件删除
@DeleteMapping("/delete/{fileName}")
@ResponseBody
public String deleteFile(@PathVariable String fileName) throws IOException {Path filePath = Paths.get(fileUploadDir).resolve(fileName).normalize();Files.deleteIfExists(filePath);return "File deleted successfully";
}
相关文章:
Spring Boot项目中实现文件的上传、下载和预览功能
在Spring Boot项目中实现文件的上传、下载和预览功能,可以通过使用Spring MVC的MultipartFile接口来处理文件上传,并使用HttpServletResponse或Resource来实现文件下载和预览。下面是如何实现这些功能的完整示例。 1. 引入依赖 确保在pom.xml中引入了S…...
【JAVA入门】Day21 - 时间类
【JAVA入门】Day21 - 时间类 文章目录 【JAVA入门】Day21 - 时间类一、JDK7前的时间相关类1.1 Date1.2 SimpleDateFormat1.3 Calendar 二、JDK8新增的时间相关类2.1 Date 相关类2.1.1 ZoneId 时区2.1.2 Instant 时间戳2.1.3 ZoneDateTime 带时区的时间 2.2 DateTimeFormat 相关…...
SQL server数据库备份和还原
新手小白都懂的sql server数据库备份和还原 一、备份 1.打开sql server数据库找到 2.展开找到对应的数据库文件 鼠标右击—任务–备份 3.复制名称 4.复制完点击添加 5.点击添加完之后再次点击查找路径 6.分别两个路径 原路径和新路径 (新路径是找到原路径新建了一…...
B站搜索建库架构优化实践
前言 搜索是B站的重要基础功能,需要对包括视频、评论、图文等海量的站内优质资源建立索引,处理来自用户每日数亿的检索请求。离线索引数据的正确、高效产出是搜索业务的基础。我们在这里分享搜索离线架构整体的改造实践:从周期长,…...
XSS反射实战
目录 1.XSS向量编码 2.xss靶场训练(easy) 2.1第一关 2.2第二关 方法一 方法二 2.3第三关 2.4第四关 2.5第五关 2.6第六关 2.7第七关 第一种方法: 第二种方法: 第三个方法: 2.8第八关 1.XSS向量编码 &…...
远程消息传递的艺术:NSDistantObject在Objective-C中的妙用
标题:远程消息传递的艺术:NSDistantObject在Objective-C中的妙用 引言 在Objective-C的丰富生态中,NSDistantObject扮演着至关重要的角色,特别是在处理分布式系统中的远程消息传递。它允许对象之间跨越不同地址空间进行通信&…...
指向派生类的基类指针、强转为 void* 再转为基类指针、此时调用虚函数会发生什么?
指向派生类的基类指针、强转为 void* 再转为基类指针、此时调用虚函数会发生什么? 1、无论指针类型怎么转,类对象内存没有发生任何变化,还是vfptr指向虚函数表,下面是成员变量,这在编译阶段就已经确定好了;…...
操作系统(Linux实战)-进程创建、同步与锁、通信、调度算法-学习笔记
1. 进程的基础概念 1.1 进程是什么? 定义: 进程是操作系统管理的一个程序实例。它包含程序代码及其当前活动的状态。每个进程有自己的内存地址空间,拥有独立的栈、堆、全局变量等。操作系统通过进程来分配资源(如 CPU 时间、内…...
react的setState中为什么不能用++?
背景: 在使用react的过程中产生了一些困惑,handleClick函数的功能是记录点击次数,handleClick函数被绑定到按钮中,每点击一次将通过this.state.counter将累计的点击次数显示在页面上 困惑: 为什么不能直接写prevStat…...
2.2算法的时间复杂度与空间复杂度——经典OJ
本博客的OJ标题均已插入超链接,点击可直接跳转~ 一、消失的数字 1、题目描述 数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗? 2、题目分析 (1)numsS…...
【CentOS 】DHCP 更改为静态 IP 地址并且遇到无法联网
文章目录 引言解决方式标题1. **编辑网络配置文件**:标题2. **确保配置文件包含以下内容**:特别注意 标题3. **重启网络服务**:标题4. **检查配置是否生效**:标题5. **测试网络连接**:标题6. **检查路由表**࿱…...
Linux 操作系统 --- 信号
序言 在本篇内容中,将为大家介绍在操作系统中的一个重要的机制 — 信号。大家可能感到疑惑,好像我在使用 Linux 的过程中并没有接触过信号,这是啥呀?其实我们经常遇到过,当我们运行的进程当进程尝试访问非法内存地址时…...
黑马前端——days09_css
案例 1 页面框架文件 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compati…...
【Python爬虫】技术深度探索与实践
目录 引言 第一部分:Python爬虫基础 1.1 网络基础 1.2 Python爬虫基本流程 第二部分:进阶技术 2.1 动态网页抓取 2.2 异步编程与并发 2.3 反爬虫机制与应对 第三部分:实践案例 第四部分:法律与道德考量 第五部分&#x…...
智启万象|挖掘广告变现潜力,保障支付安全便捷
谷歌致力于为开发者提供 先进的广告变现与支付解决方案 一起回顾 2024 Google 开发者大会 了解如何利用谷歌最新工具和功能 提高变现收入,优化用户体验,保障交易安全 让变现更上一层楼 广告检查器是谷歌 AdMob 平台最新推出的高级测试工具,开…...
函数递归,匿名、内置行数,模块和包,开发规范
一、递归与二分法 一)递归 1、递归调用的定义 递归调用:在调用一个函数的过程中,直接或间接地调用了函数本身 2、递归分为两类:直接与间接 #直接 def func():print(from func)func()func() # 间接 def foo():print(from foo)bar…...
Springboot3 整合swagger
一、pom.xml <dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-api</artifactId><version>2.1.0</version></dependency> 二、application.yml # SpringDoc配置 # springdoc:swa…...
查看同一网段内所有设备的ip
使用命令提示符(CMD)进行扫描 查看本机IP地址 首先通过 ipconfig /all 命令查看本机的IP地址,确定你的网段,例如 192.168.1.。 Ping网段内每个IP地址 接着使用循环命令: for /L %i IN (1,1,254) DO ping -w 1 -n …...
Spark MLlib 特征工程(上)
文章目录 Spark MLlib 特征工程(上)特征工程预处理 Encoding:StringIndexer特征构建:VectorAssembler特征选择:ChiSqSelector归一化:MinMaxScaler模型训练总结Spark MLlib 特征工程(上) 前面我们一起构建了一个简单的线性回归模型,来预测美国爱荷华州的房价。从模型效果来…...
《SPSS零基础入门教程》学习笔记——03.变量的统计描述
文章目录 3.1 连续变量(1)集中趋势(2)离散趋势(3)分布特征 3.2 分类变量(1)单个分类变量(2)多个分类变量 3.1 连续变量 (1)集中趋势 …...
耳机音频测量技术:标准、方法与工程实践
1. 耳机音频测量技术概述在音频设备研发和质量控制领域,耳机性能的客观测量一直是个技术难点。与扬声器测量不同,耳机测量需要模拟人耳的真实声学环境,这就涉及到复杂的耦合腔体设计和标准化的测量方法。IEC 60268-7作为国际电工委员会发布的…...
机场混凝土道面摊铺车辆行驶控制【附方案】
✨ 长期致力于履带式车辆、滑模摊铺、道面边界检测、轨迹规划、行驶控制器研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流,点击《获取方式》 (1)多模态道面边界检测与卡尔曼…...
Browser-Use:基于LLM的智能浏览器自动化框架入门与实践
1. 项目概述:当AI学会“上网冲浪” 如果你和我一样,在过去的几年里尝试过各种RPA工具或者写爬虫脚本来处理网页上的重复性工作,那你一定对那种“脚本一跑就崩,网站一改版就废”的体验深有感触。我们总在幻想,要是能直…...
《第一大道》铺前路,《凰标》立后世千年文化准则@凤凰标志
任何一场完整的文化复兴,必然包含两个阶段: 先破局开路,再立序定规。 无破局,则无出路;无定规,则无长存。一破 一立破局立规《第一大道》《凰标》武 突围 开荒 破弊文 守正 定调 传世让众生有路可走…...
8088单板机DIY--串口转换(一)
1.USB转232电路2.功能测试打开设备管理器,可以看到新增的串口。3.通讯测试短接发送和接收,进行自发自收测试。...
GPU加速的时序驱动布局优化方法解析
1. 时序驱动布局优化:GPU加速的关键路径分析方法在超大规模集成电路(VLSI)物理设计流程中,布局阶段的质量直接影响芯片的时序收敛和最终性能。传统布局算法主要关注线长和拥塞优化,对时序指标的考虑相对间接。随着工艺节点不断进步࿰…...
深度拆解GPT-Realtime-2:从“能听会说”到“听懂人话”,靠的是什么?
请你想象这个场景: 你打电话订酒店,中途改主意3次,还接了另一个电话。AI全程没让你重复一句话。——这就是GPT-Realtime-2做到的事。三大模型,三类场景的精准切割OpenAI此次发布的核心策略是专业化分工:GPT-Realtime-2…...
对话记忆与上下文管理:Spring AI 实现多轮会话与持久化存储
系列导读 你现在看到的是《Spring AI 企业级集成与场景实践:从零搭建智能应用》的第 3/10 篇,当前这篇会重点解决:教会读者如何在 Spring AI 中优雅地管理对话上下文,避免重复输入和 Token 浪费。 上一篇回顾:第 2 篇《多模型适配实战:在 Spring AI 中统一管理 OpenAI、…...
新人如何快速融入技术团队?这5个细节决定你的第一印象
对于软件测试工程师而言,加入一个新的技术团队,挑战远不止于记住人名和门禁密码。你将面对的是一套陌生的系统架构、一份可能长达数百页的需求文档、一个仍在迭代中的自动化测试框架,以及一群拥有不同技术背景和沟通风格的开发伙伴。在这样的…...
云原生任务调度引擎tausik-core:设计、实践与高可用部署
1. 项目概述:一个面向未来的云原生应用核心引擎最近在梳理团队的技术栈,发现一个挺有意思的现象:很多项目在向云原生转型时,总会遇到一个“核心引擎”的选择难题。是直接上Kubernetes全家桶,还是基于某个框架自研&…...
