Spring MVC中实现一个文件上传和下载功能

news2024/11/17 14:53:36

说到文件上传和下载,相信每个开发者都有或多或少的接触过文件上传的功能吧,文件上传和下载是我们在学习计算机网络应用常见的一个功能,主要涉及到用户和服务器之间的数据传输。

我们来对文件上传和下载功能的进行相关概述吧!

文件上传

定义:文件上传是指用户将本地计算机上的文件通过网络传输到服务器的过程。用户通常通过网页表单选择文件并提交,服务器接收并存储该文件。

过程:

  1. 用户选择文件:用户在网页上选择要上传的文件,通常通过一个文件输入框(<input type="file">)。
  2. 表单提交:用户点击提交按钮,浏览器将文件和其他表单数据一起发送到服务器。
  3. HTTP请求:浏览器发起一个HTTP POST请求,包含文件数据和其他表单字段。
  4. 服务器接收文件
    • 服务器接收到请求后,解析请求体中的文件数据。
    • 服务器将文件存储在指定的目录中。
  5. 反馈结果:服务器处理完上传后,通常会返回一个响应,告知用户上传是否成功。

文件下载

定义:文件下载是指用户从服务器获取文件并保存到本地计算机的过程。用户通常通过点击链接或按钮来触发下载。

过程:

  1. 用户请求下载:用户在网页上点击下载链接或按钮,触发下载请求。
  2. HTTP请求:浏览器发起一个HTTP GET请求,请求特定的文件。
  3. 服务器处理请求
    • 服务器接收到请求后,查找请求的文件。
    • 服务器将文件内容写入HTTP响应体,并设置适当的响应头(如Content-Disposition)以指示浏览器下载文件而不是直接显示。
  4. 浏览器接收文件:浏览器接收到响应后,开始下载文件并提示用户选择保存位置。
  5. 文件保存:用户选择保存位置后,文件被下载到本地计算机。

文件上传和下载的关键步骤

在文件上传和下载的过程中,涉及以下关键步骤:

  1. 用户界面:提供文件选择和下载的用户界面(HTML表单)。
  2. HTTP请求:使用适当的HTTP方法(POST用于上传,GET用于下载)发送请求。
  3. 请求处理:服务器端代码处理请求,解析文件数据(上传)或查找文件(下载)。
  4. 文件存储:在上传过程中,将文件存储在服务器的指定位置。
  5. 响应返回:服务器返回处理结果(上传成功/失败)或文件内容(下载)。
  6. 错误处理:处理可能出现的错误,如文件大小限制、文件类型验证、文件不存在等。

在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 {

    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine);
        resolver.setCharacterEncoding("UTF-8");
        resolver.setOrder(1);
        return resolver;
    }

    @Bean
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(10485760); // 10MB
        return multipartResolver;
    }

    @Override
    public 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2167043.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL事务、索引、数据恢复和备份

MySQL事务、索引、数据恢复和备份 1.MySQL的事务处理 事务就是将一组SQL语句放在同一批次内去执行 如果一个SQL语句出错&#xff0c;则该批次内的所有SQL都将被取消执行 MySQL的事务实现方法 : SET AUTOCOMMIT 使用SET语句来改变自动提交模式 SET AUTOCOMMIT 0; # 关…

测试干货 | 一文读懂工业CT检测技术—无损检测手段

撰文排版&#xff1a;刘佳 审核指导&#xff1a;肖俊灵 “研路漫漫&#xff0c;伴你同行” 本文较长&#xff0c;建议先收藏后随时查看&#xff01;以后我们将更新更多此类硬核科普&#xff0c;欢迎关注&#xff01; 工业CT&#xff0c;即工业计算机断层成像技术&#xff0c;作…

舞台灯细绿激光模组安装方式

在追求视觉盛宴的现代舞台艺术中&#xff0c;细绿激光模组以其独特的色彩、高亮度和精准性&#xff0c;成为了不可或缺的创意元素。舞台灯细绿激光模组不仅能营造出梦幻般的氛围&#xff0c;还能通过精准的光束定位&#xff0c;引领观众视线&#xff0c;增强表演的层次感和沉浸…

大浪淘沙下的金融智变:AGI入场,巨头们已经吃到了第一波红利

长久以来&#xff0c;金融行业始终是全球 AI 技术投入的最大领域&#xff0c;其中银行这一细分市场的 AI 投资金额就占据了全球 AI 市场的超过 10%&#xff0c;无疑成为了 AI 实践的先锋。在国内市场&#xff0c;这一趋势同样显著且强劲。2024 年上半年的大模型招标统计数据显示…

《论软件架构建模技术与应用》写作框架,软考高级系统架构设计师

论文真题 软件架构风格是描述一类特定应用领域中系统组织方式的惯用模式&#xff0c;反映了领域中诸多系统所共有的结构特征和语义特征&#xff0c;并指导如何将各个模块和子系统有效组织成一个完整的系统。分层架构是一种常见的软件架构风格&#xff0c;能够有效简化设计&…

世优科技“1+2+N”,助力湖南旅发大会“火出圈”

刚刚&#xff0c;第三届湖南旅游发展大会在衡阳盛大启幕&#xff0c;现场&#xff0c;世优科技团队通过“12N”模式&#xff08;即&#xff1a;1个IP复活&#xff0c;2项技术突破&#xff0c;N个场景应用&#xff09;&#xff0c;助力衡阳市IP“火出圈”3D形象惊艳亮相&#xf…

支付宝开放平台-开发者社区——AI 日报「9 月 26 日」

1 突破数据墙&#xff01;27岁华裔MIT辍学创业8年&#xff0c;年化收入逼近10亿 新智元&#xff5c;阅读原文 就在刚刚&#xff0c;创业成功的27岁亿万富翁Alexandr Wang宣布——Scale AI的年化收入&#xff0c;几乎达到了10亿美元&#xff01;Scale AI主攻的就是如今AI模型…

BACnet协议-(基于ISO 8802-3 UDP)(2)

1、模拟设备的工具界面如下&#xff1a; 2、使用yet another bacnet explorer 用作服务&#xff0c;用于发现设备&#xff0c;界面如下&#xff1a; 3、通过wireshark 抓包如下&#xff1a; &#xff08;1&#xff09;、整体包如下&#xff1a; &#xff08;2&#xff09;、m…

AI制作30秒疗愈视频,单月变现9万+,这才是顶流赛道!

用AI做短视频&#xff0c;赚流量分成&#xff0c;一个月竟然能月赚9万元&#xff0c;毫不夸张的说已经能够媲美二线城市普通上班族全年收入&#xff01; 在国外社交平台YouTube油管上的账号&#xff0c;仅仅只用一段30秒的风景空镜头&#xff0c;配上一段纯文字的情感鸡汤&…

【GUI设计】基于图像分割和边缘算法的GUI系统(7),matlab实现

博主简介&#xff1a; 如需获取设计的完整源代码或者有matlab图像代码项目需求/合作&#xff0c;可联系主页个人简介提供的联系方式或者文末的二维码。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于图像分割和边缘算法的GUI系统…

[Redis][Zset]详细讲解

目录 0.前言1.常见命令1.ZADD2.ZCARD3.ZCOUNT4.ZRANGE5.ZREVRANGE6.ZRANGEBYSCORE7.ZPOPMAX8.BZPOPMAX9.ZPOPMIN10.BZPOPMIN11.ZRANK12.ZREVRANK13.ZSCORE14.ZREM15.ZREMRANGEBYRANK16.ZREMRANGEBYSCORE17.ZINCRBY 2.集合间操作1.有序集合的交集操作2.ZINTERSTORE3.有序集合的并…

ROS-noetic自定义action文件进行通信

前言 本系统的系统是Ubuntu20.04的ros-noetic&#xff0c;本文讲述了通过创建 ROS 节点&#xff08;服务器和客户端&#xff09;的完整流程&#xff0c;使用 Action 实现从 1 到 N 的累加和&#xff0c;并在计算过程中向客户端发送进度反馈。 整体概述 创建功能包&#xff1a;…

多线程极速导出/9字段10W行只需2秒/导入导出打印组件/功能丰富简单易用

一、功能特点 组件同时集成了导出数据到csv、xls、pdf和打印数据。所有操作全部提供静态方法无需new&#xff0c;数据和属性等各种参数设置采用结构体数据&#xff0c;极为方便。同时支持QTableView、QTableWidget、QStandardItemModel、QSqlTableModel等数据源。提供静态方法…

如何使用GitHub Desktop管理GitLab库

不管是新手还是老手&#xff0c;Github Desktop都是在苹果系统和Windows系统上管理与创建项目的不错的方式&#xff0c;GitHub Desktop都能够让在GitHub上的工作流更为简单快捷。 注意&#xff0c;以下步骤只支持原版的GitHub Desktop 第一步 从这下载GitHub Desktop打开你的G…

CSS中<a>超链接的样式

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><!-- 伪类选择器 -->&…

大模型RAG入门到实战基础教程(非常详细),大模型RAG入门到精通,收藏这一篇就够了!

写在前面 大模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;的浪潮已经席卷了几乎各行业&#xff0c;但当涉及到专业场景或行业细分域时&#xff0c;通用大模型就会面临专业知识不足的问题。相对于成本昂贵的“Post Train”或“SFT”&#xff0c;基于RAG的技…

css 中 ~ 符号的使用

直接看代码 <script setup> </script><template><div class"container"><p><a href"javascript:;">纪检委</a><a href"javascript:;">中介为</a><a href"javascript:;">…

Vxe UI vue 使用 vxe-form 表单实现简历模板

Vxe UI 使用 vxe-form 表单实现简历模板 查看 github <template><div><p>边框&#xff1a;<vxe-switch v-model"border"></vxe-switch>标题背景&#xff1a;<vxe-switch v-model"titleBackground"></vxe-switch&…

【GreenHills】使用“gsrec”命令生成二进制文件

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 记录在GHS中修改工程命令&#xff0c;输出hex&#xff0c;bin文件等&#xff0c;对问题进行快速答疑&#xff0c;GHS编译器如何去使用”gsrec“生成不同的二进制文件。 2、 问题场景 客户想要生成hex&#xff0c;bi…

【每日一题】LeetCode 2306.公司命名(位运算、数组、哈希表、字符串、枚举)

【每日一题】LeetCode 2306.公司命名&#xff08;位运算、数组、哈希表、字符串、枚举&#xff09; 题目描述 给定一个字符串数组 ideas&#xff0c;表示在公司命名过程中使用的名字列表。我们需要从 ideas 中选择两个不同的名字&#xff0c;称为 ideaA 和 ideaB。然后交换 i…