Spring MVC中实现一个文件上传和下载功能
说到文件上传和下载,相信每个开发者都有或多或少的接触过文件上传的功能吧,文件上传和下载是我们在学习计算机网络应用常见的一个功能,主要涉及到用户和服务器之间的数据传输。
我们来对文件上传和下载功能的进行相关概述吧!
文件上传
定义:文件上传是指用户将本地计算机上的文件通过网络传输到服务器的过程。用户通常通过网页表单选择文件并提交,服务器接收并存储该文件。
过程:
- 用户选择文件:用户在网页上选择要上传的文件,通常通过一个文件输入框(
<input type="file">)。 - 表单提交:用户点击提交按钮,浏览器将文件和其他表单数据一起发送到服务器。
- HTTP请求:浏览器发起一个HTTP POST请求,包含文件数据和其他表单字段。
- 服务器接收文件:
- 服务器接收到请求后,解析请求体中的文件数据。
- 服务器将文件存储在指定的目录中。
- 反馈结果:服务器处理完上传后,通常会返回一个响应,告知用户上传是否成功。
文件下载
定义:文件下载是指用户从服务器获取文件并保存到本地计算机的过程。用户通常通过点击链接或按钮来触发下载。
过程:
- 用户请求下载:用户在网页上点击下载链接或按钮,触发下载请求。
- HTTP请求:浏览器发起一个HTTP GET请求,请求特定的文件。
- 服务器处理请求:
- 服务器接收到请求后,查找请求的文件。
- 服务器将文件内容写入HTTP响应体,并设置适当的响应头(如Content-Disposition)以指示浏览器下载文件而不是直接显示。
- 浏览器接收文件:浏览器接收到响应后,开始下载文件并提示用户选择保存位置。
- 文件保存:用户选择保存位置后,文件被下载到本地计算机。
文件上传和下载的关键步骤
在文件上传和下载的过程中,涉及以下关键步骤:
- 用户界面:提供文件选择和下载的用户界面(HTML表单)。
- HTTP请求:使用适当的HTTP方法(POST用于上传,GET用于下载)发送请求。
- 请求处理:服务器端代码处理请求,解析文件数据(上传)或查找文件(下载)。
- 文件存储:在上传过程中,将文件存储在服务器的指定位置。
- 响应返回:服务器返回处理结果(上传成功/失败)或文件内容(下载)。
- 错误处理:处理可能出现的错误,如文件大小限制、文件类型验证、文件不存在等。
在SpringMVC中实现一个文件上传和下载的功能
第一步创建我们的文件项目目录结构:
src└── main├── java│ └── com│ └── example│ └── fileupload│ ├── FileUploadController.java│ └── WebConfig.java├── resources│ └── templates│ └── upload.html└── web.xml
第二步:添加相关依赖
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.10</version></dependency><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId><version>3.0.12.RELEASE</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency>
</dependencies>
第三步,创建我们的Web配置类,用来监听相关信息
在WebConfig.java中配置Spring MVC:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {@Beanpublic ViewResolver viewResolver(SpringTemplateEngine templateEngine) {ThymeleafViewResolver resolver = new ThymeleafViewResolver();resolver.setTemplateEngine(templateEngine);resolver.setCharacterEncoding("UTF-8");resolver.setOrder(1);return resolver;}@Beanpublic CommonsMultipartResolver multipartResolver() {CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();multipartResolver.setMaxUploadSize(10485760); // 10MBreturn multipartResolver;}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/uploads/**").addResourceLocations("file:uploads/");}
}
创建控制器
在FileUploadController.java中实现文件上传和下载的逻辑:
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;@Controller
public class FileUploadController {private final String uploadDir = "uploads/";@GetMapping("/")public String index() {return "upload";}@PostMapping("/upload")public String uploadFile(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {if (file.isEmpty()) {redirectAttributes.addFlashAttribute("message", "请选择一个文件上传!");return "redirect:/";}try {// 保存文件File dir = new File(uploadDir);if (!dir.exists()) {dir.mkdirs();}File uploadedFile = new File(uploadDir + file.getOriginalFilename());file.transferTo(uploadedFile);redirectAttributes.addFlashAttribute("message", "文件上传成功:" + file.getOriginalFilename());} catch (IOException e) {redirectAttributes.addFlashAttribute("message", "文件上传失败:" + e.getMessage());}return "redirect:/";}@GetMapping("/download")public void downloadFile(@RequestParam("filename") String filename, HttpServletResponse response) {File file = new File(uploadDir + filename);if (file.exists()) {response.setContentType("application/octet-stream");response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");try (FileInputStream in = new FileInputStream(file);OutputStream out = response.getOutputStream()) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = in.read(buffer)) != -1) {out.write(buffer, 0, bytesRead);}} catch (IOException e) {e.printStackTrace();}} else {response.setStatus(HttpServletResponse.SC_NOT_FOUND);}}
}
第五步,创建HTML模板
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>文件上传</title>
</head>
<body>
<h1>文件上传</h1><form method="post" enctype="multipart/form-data" th:action="@{/upload}"><input type="file" name="file" required/><button type="submit">上传</button>
</form><div th:if="${message}" th:text="${message}"></div><h2>下载文件</h2>
<form method="get" th:action="@{/download}"><input type="text" name="filename" placeholder="输入文件名" required/><button type="submit">下载</button>
</form>
</body>
</html>
最后一步,配置web.xml文件
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><servlet><servlet-name>dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/</url-pattern></servlet-mapping><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener></web-app>

14:18:08.583 [http-nio-8008-exec-6] DEBUG org.springframework.web.servlet.DispatcherServlet - POST "/SpringMVC/upload", parameters={}
14:18:08.595 [http-nio-8008-exec-6] DEBUG org.springframework.web.multipart.commons.CommonsMultipartResolver - Part 'file', size 719635 bytes, filename='白底logo.png'
14:18:08.596 [http-nio-8008-exec-6] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.miaow.controller.FileUploadController#uploadFile(MultipartFile, RedirectAttributes)
14:18:08.600 [http-nio-8008-exec-6] DEBUG org.springframework.web.multipart.commons.CommonsMultipartFile - Part 'file', filename '白底logo.png': moved to [D:\IDEATomcat\apache-tomcat-9.0.89-windows-x64\apache-tomcat-9.0.89\bin\uploads\白底logo.png]
14:18:08.600 [http-nio-8008-exec-6] DEBUG org.springframework.web.servlet.view.RedirectView - View name 'redirect:', model {}
14:18:08.601 [http-nio-8008-exec-6] DEBUG org.springframework.web.multipart.commons.CommonsMultipartResolver - Cleaning up part 'file', filename '白底logo.png'
14:18:08.601 [http-nio-8008-exec-6] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 302 FOUND
14:18:08.608 [http-nio-8008-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/SpringMVC/", parameters={}
14:18:08.608 [http-nio-8008-exec-5] DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped to ParameterizableViewController [view="index"]
14:18:08.610 [http-nio-8008-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
14:18:12.924 [http-nio-8008-exec-10] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/SpringMVC/upload", parameters={}
14:18:12.924 [http-nio-8008-exec-10] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.miaow.controller.FileUploadController#index()
14:18:12.925 [http-nio-8008-exec-10] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
上传成功日志。
下载成功日志:
14:19:16.956 [http-nio-8008-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/SpringMVC/download?filename=violet.webp", parameters={masked}
14:19:16.956 [http-nio-8008-exec-9] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.miaow.controller.FileUploadController#downloadFile(String, HttpServletResponse)
14:19:16.958 [http-nio-8008-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
相关文章:
Spring MVC中实现一个文件上传和下载功能
说到文件上传和下载,相信每个开发者都有或多或少的接触过文件上传的功能吧,文件上传和下载是我们在学习计算机网络应用常见的一个功能,主要涉及到用户和服务器之间的数据传输。 我们来对文件上传和下载功能的进行相关概述吧! 文…...
Webpack 介绍
Webpack 介绍 Date: August 29, 2024 全文概要 Webpack概念: Webpack是一个静态的模块化的打包工具,可以为现代的 JavaSript 应用程序进行打包。 1-静态:Webpack可以将代码打包成最终的静态资源 2-模块化:webpack支持各种模块…...
在Linux实时监控某个应用是否运行,未运行,执行运行命令
1、shell脚本(每隔30秒检测一次) 脚本要注意的地方是:在Nodepad编辑的时候要使用Unix(LF)格式,避免在Linux无法执行命令 #!/bin/bash# RabbitMQ进程名称(可能需要根据你的安装进行调整) RABBITMQ_PROCE…...
Serilog文档翻译系列(六) - 可用的接收器、增强器、格式化输出
01、提供的接收器 Serilog 使用接收器将日志事件以各种格式写入存储。许多接收器由更广泛的 Serilog 社区开发和支持;可以通过在 NuGet 上搜索 serilog 标签找到。 02、增强器 日志事件可以通过多种方式增强属性。通过 NuGet 提供了一些预构建的增强器ÿ…...
傅里叶级数在机器人中的应用(动力学参数辨识)
B站首发!草履虫都能看懂的【傅里叶变换】讲解,清华大学李永乐老师教你如何理解傅里叶变换,辨清美颜和变声原理,!!_哔哩哔哩_bilibiliB站首发!草履虫都能看懂的【傅里叶变换】讲解,清…...
前端框架Vue、React、Angular、Svelte对比
在对比 React、Vue.js、Angular 和 Svelte 时,除了在高层次的特性上有显著差异,它们在核心设计理念和底层实现机制上也有明显的不同。为了清晰地理解这些框架,我们可以从以下几个方面来分析它们的核心不同点和底层不同点。 1. 框架类型和设计…...
深度学习后门攻击分析与实现(二)
前言 在本系列的第一部分中,我们已经掌握了深度学习中的后门攻击的特点以及基础的攻击方式,现在我们在第二部分中首先来学习深度学习后门攻击在传统网络空间安全中的应用。然后再来分析与实现一些颇具特点的深度学习后门攻击方式。 深度学习与网络空间…...
boost 的lockfree 使用
boost 的lockfree 使用 // test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <mutex> #include <memory> #include <condition_variable> #include <…...
基于Hexo个人博客界面优化
基于Hexo个人博客界面优化 怎么搭建个人博客 选择主题 经过多个对比,选择简单一点的的yilia 1.将主题文件下载解压到 你的博客目录的 themes下 下载yilia主题文件 2.改写配置 打开你的_config.yml #theme: landscape 这是原来的,改成下面这个 theme: yil…...
vue3+ts不能将类型“Timeout”分配给类型“null”不能将类型“Timeout”分配给类型number
在设置有setTimeout() 函数时,一般是需要进行清除计时器操作的; 常用的做法是定义一个全局变量timer,在onMounted或者有需要的地方进行赋值,在onBeforeUnmount进行clear,一般在定义timer变量时,使用 numbe…...
如何给多台Linux机器设置时间同步
文章目录 1,使用chrony时间同步服务1.1 修改chrony配置文件 2,使用ntpdate服务 1,使用chrony时间同步服务 Centos7默认已安装,另外基于centos7的统信OS,中科OS也会默认安装这个。如果你机器上没有这个服务,…...
忘写return有什么现象?
使用C语言,一直觉得没有return无所谓,直到被制裁。。 参考: 非void函数缺失返回值导致crash或结果异常的分析 - 知乎 (zhihu.com) 可以分析出: 没有写return 的话,eax的内容是在预期之外的。 例如更新参考内容的解…...
大数据新视界 --大数据大厂之 Druid 实时数据分析平台在大数据中的应用
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...
MySQL --基本查询(下)
文章目录 3.Update3.1将孙悟空同学的数学成绩变更为 80 分3.2将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分3.3将总成绩倒数前三的 3 位同学的数学成绩加上 30 分3.4将所有同学的语文成绩更新为原来的 2 倍 4.Delete4.1删除数据4.1.1删除孙悟空同学的考…...
vue3实现自定义主题色切换功能
目录 1.添加theme样式文件2.引入样式文件3.使用变量设置css样式4.设置主题样式5.切换方法 1.添加theme样式文件 文件内容如下: html[data-theme"light"]{--text-color: #000000;/* 写需要切换的样式 */ } html[data-theme"dark"]{--text-color…...
不懂性能测试,被面试官挂了...
性能测试旨在检查应用程序或软件在特定负载下工作时的响应性和稳定性,从而检测应用程序/软件在响应速度、可扩展性和稳定性方面是否达到预期的要求。 简而言之,性能测试目标就是为了识别并消除应用程序中的性能瓶颈。 本文将为大家详细介绍性能测试主要…...
JS逆向基础-谷歌浏览器调试技巧(详细)
概述 浏览器的调试工具在 JavaScript 逆向工程中,帮助开发者分析和理解代码执行流程、变量值及其变化,从而揭示隐藏逻辑和加密机制,为破解、修改或复现代码提供重要支持。 调试面板详解 谷歌浏览器的调试面板概览: 顶部操作栏 …...
那年我双手插兜,使用IPv6+DDNS动态域名解析访问NAS
估计有很多科技宅和我一样,会买一个NAS存储或者自己折腾刷一下黑群晖玩玩,由于运营商不给分配固定的公网IP,就导致我在外出的时候无法访问家里的NAS,于是远程访问常常受到IP地址频繁变动的困扰。为了解决这一问题,结合…...
CSS的弹性盒子模型(Flex box)
弹性盒子模型是CSS3的一种新的布局模式,弹性盒是一种当页面需要适应不同的屏幕大小以及设备类型时确保拥有合适的布局方式,引入弹性盒子模型的目的时提供更加有效的方式来对一个容器中的子元素进行排列,对齐和分配空白空间。 弹性盒子由弹性容…...
django drf 分页器
自定义分页器代码: from django.core.paginator import InvalidPage from django.core.paginator import Paginator as DjangoPaginator from django.utils.functional import cached_property from rest_framework.exceptions import NotFound from rest_framewor…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
