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…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...
Django RBAC项目后端实战 - 03 DRF权限控制实现
项目背景 在上一篇文章中,我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统,为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...
大数据驱动企业决策智能化的路径与实践
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:数据驱动的企业竞争力重构 在这个瞬息万变的商业时代,“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...
Java中栈的多种实现类详解
Java中栈的多种实现类详解:Stack、LinkedList与ArrayDeque全方位对比 前言一、Stack类——Java最早的栈实现1.1 Stack类简介1.2 常用方法1.3 优缺点分析 二、LinkedList类——灵活的双端链表2.1 LinkedList类简介2.2 常用方法2.3 优缺点分析 三、ArrayDeque类——高…...