当前位置: 首页 > news >正文

【Spring MVC】小文件上传的多种方法

文章目录

  • 方法参数
  • 单文件上传
    • 1. MultipartFile 的 transferTo(File dest)
    • 2. MultipartFile 的 transferTo(Path dest)
    • 3. MultipartFile + Files.write(Path path, byte[] bytes, OpenOption... options)
    • 4. MultipartFile + Files.copy(InputStream in, Path target, CopyOption... options)
    • 5. HttpServletRequest 的 getPart(String var1)
  • 多文件上传(兼容单文件)
    • 1. MultipartFile[ ] + 前四种上传方法
    • 2. List<MultipartFile> + 前四种上传方法
    • 3. MultipartHttpServletRequest + 前四种上传方法
    • 4. HttpServletRequest 的 getParts()
  • 补充
  • 总结

Win、JDK 17、 Spring Boot 3.1.2

方法参数

  1. Spring 的 MultipartFile(最常用)
  2. Spring 的 MultipartHttpServletRequest
  3. Servlet 的 HttpServletRequest(原生)

单文件上传

1. MultipartFile 的 transferTo(File dest)

@PostMapping("/upload-1")
public String upload1(@RequestPart("file") MultipartFile mf) throws IOException {String filename = mf.getOriginalFilename();mf.transferTo(new File("d:/", filename));return "upload success";
}

2. MultipartFile 的 transferTo(Path dest)

@PostMapping("/upload-2")
public String upload2(@RequestParam("file") MultipartFile mf) throws IOException {String filename = mf.getOriginalFilename();Path path = Paths.get("upload", filename);mf.transferTo(path);return "upload success";
}

3. MultipartFile + Files.write(Path path, byte[] bytes, OpenOption… options)

@PostMapping("/upload-3")
public String upload3(@RequestParam("file") MultipartFile mf) throws IOException {String filename = mf.getOriginalFilename();Path path = Paths.get("upload", filename);Files.write(path, mf.getBytes());return "upload success";
}

4. MultipartFile + Files.copy(InputStream in, Path target, CopyOption… options)

@PostMapping("/upload-4")
public String upload4(@RequestParam("file") MultipartFile mf) throws IOException {String filename = mf.getOriginalFilename();Path path = Paths.get("upload", filename);// 若文件已存在,则会抛出 FileAlreadyExistsExceptionFiles.copy(mf.getInputStream(), path);return "upload success";
}

5. HttpServletRequest 的 getPart(String var1)

public String upload8(HttpServletRequest req) throws ServletException, IOException {// 获取上传的文件流,单文件Part filePart = req.getPart("file");String filename = filePart.getSubmittedFileName();// 构建目标文件对象Path path = Paths.get("upload", filename);byte[] bytes = filePart.getInputStream().readAllBytes();InputStream in = filePart.getInputStream();// Files.write(path, bytes);// Files.copy(in,path);return "upload success";
}

多文件上传(兼容单文件)

1. MultipartFile[ ] + 前四种上传方法

@PostMapping("/upload-5")
public String upload5(@RequestParam("files") MultipartFile[] files) {for (MultipartFile mf : files) {// 同理又有四种// mf.transferTo(File dest)// mf.transferTo(Path dest)// Files.write(Path path, byte[] bytes, OpenOption... options)// Files.copy(mf.getInputStream(), path);}return "upload success";
}

2. List<MultipartFile> + 前四种上传方法

@PostMapping("/upload-6")
public String upload6(@RequestParam("files") List<MultipartFile> files) {for (MultipartFile mf : files) {// 同理又有四种// mf.transferTo(File dest)// mf.transferTo(Path dest)// Files.write(Path path, byte[] bytes, OpenOption... options)// Files.copy(mf.getInputStream(), path);}return "upload success";
}

3. MultipartHttpServletRequest + 前四种上传方法

@PostMapping("/upload-7")
public String upload7(MultipartHttpServletRequest req) {req.getFileNames().forEachRemaining(name -> {for (MultipartFile mf : req.getFiles(name)) {// 同理又有四种// mf.transferTo(File dest)// mf.transferTo(Path dest)// Files.write(Path path, byte[] bytes, OpenOption... options)// Files.copy(mf.getInputStream(), path);}});return "upload success";
}

4. HttpServletRequest 的 getParts()

@PostMapping("/upload-9")
public String upload9(HttpServletRequest req) throws ServletException, IOException {Collection<Part> parts = req.getParts();for (Part part : parts) {String filename = part.getSubmittedFileName();Path path = Paths.get("upload", filename);byte[] bytes = part.getInputStream().readAllBytes();InputStream in = part.getInputStream();// Files.write(path, bytes);// Files.copy(in,path);}return "upload success";
}

补充

以上方法仅为示例代码,注意 NPE
以上方法仅适用于小文件上传,不适合上百 MB 的大文件上传
Files.copy() 无法覆盖文件,会抛异常
@RequestPart 可替代 @RequestParam

@RequestParam@RequestPart 都是Spring框架中用于处理HTTP请求参数的注解,但它们在处理文件上传时有一些区别。

  1. @RequestParam:

    • 用于处理普通的表单字段和查询参数,适用于处理常规的请求参数。
    • 在处理文件上传时,可以用于接收文件的元数据(如文件名、大小等),但无法直接获取文件的内容。
    • 对于文件上传,@RequestParam 需要配合 MultipartFile 类型参数来获取文件的内容。

    示例:

    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file) {// 处理文件上传逻辑// ...
    }
    
  2. @RequestPart:

    • 用于处理文件上传请求,特别适用于处理发送 multipart/form-data 类型的请求。
    • 允许直接获取文件的内容,不需要再额外使用 MultipartFile 类型参数来获取文件内容。
    • 可以用于接收文件的元数据(如文件名、大小等),也可以直接获取文件的字节流。

    示例:

    @PostMapping("/upload")
    public String handleFileUpload(@RequestPart("file") byte[] fileBytes,@RequestPart("file") InputStream fileInputStream,@RequestPart("file") Part filePart) {// 处理文件上传逻辑// ...
    }
    

综上所述,@RequestParam 用于处理常规的请求参数和文件元数据,需要额外使用 MultipartFile 类型参数来获取文件内容。而 @RequestPart 则更适用于处理文件上传请求,允许直接获取文件的内容,并且可以用于接收文件元数据。

在实际使用中,你可以根据请求的具体内容和需求来选择合适的注解,以及结合相应的处理方式。如果仅处理文件上传,使用 @RequestPart 更为直接方便;如果需要处理普通请求参数和文件上传一起,可以使用 @RequestParam 来处理。

总结

Spring MVC 提供了多种方法来处理文件上传,开发者可以根据项目需求和性能考虑选择适合的方法。对于小文件上传,使用 MultipartFile 接口是简单有效的选择。

无论选择哪种方法,都应该注意文件上传过程中的安全性和性能,避免潜在的漏洞和性能问题。合理设置文件大小限制,处理异常情况,以及对文件上传进行必要的验证和授权,都是保障文件上传功能正常运作的重要因素。

相关文章:

【Spring MVC】小文件上传的多种方法

文章目录 方法参数单文件上传1. MultipartFile 的 transferTo(File dest)2. MultipartFile 的 transferTo(Path dest)3. MultipartFile Files.write(Path path, byte[] bytes, OpenOption... options)4. MultipartFile Files.copy(InputStream in, Path target, CopyOption..…...

UE5.1移动端PreintegratedSkinBxDF解析

Part 1 头文件 MobileBasePassPixelShader.usf 主要看Main函数&#xff1a; #if MOBILE_MULTI_VIEWResolvedView ResolveView(BasePassInterpolants.MultiViewId); #elseResolvedView ResolveView(); #endif这玩意Shader文件找不到&#xff0c;感觉是个全局变量的东西。万幸…...

WebSocket心跳机制(笔记大全)

一、WebSocket心跳机制前端 前端实现WebSocket心跳机制的方式主要有两种&#xff1a; 使用setInterval定时发送心跳包。在前端监听到WebSocket的onclose()事件时&#xff0c;重新创建WebSocket连接。 第一种方式会对服务器造成很大的压力&#xff0c;因为即使WebSocket连接正…...

Spring Boot日志:SLF4J和Logback

日志的分类 SpringBoot中的日志库分为两种&#xff1a; 实现库&#xff1a;提供具体的日志实现&#xff0c;例如日志级别的控制、打印格式、输出目标等。外观库&#xff1a;自身不提供日志实现&#xff0c;而是对其他日志库进行封装&#xff0c;从而方便使用。基于外观模式实…...

[C++] C++入门第二篇 -- 引用 -- 内联函数inline -- auto+for

目录 1、引用 -- & 1.1 引用的概念 1.2 引用特性 1.3 常引用 -- 权限问题 1.4 引用的使用场景 1.4.1 做参数 1.4.2 做返回值 注意 1.5 传值、传引用的效率比较 1.6 引用和指针的区别 2、内联函数 2.1 概念 转存失败重新上传取消​编辑转存失败重新上传取消​编…...

Latex | 将MATLAB图并导入Latex中的方法

一、问题描述 用Latex时写paper时&#xff0c;要导入MATLAB生成的图进去 二、解决思路 &#xff08;1&#xff09;在MATLAB生成图片的窗口中&#xff0c;导出.eps矢量图 &#xff08;2&#xff09;把图上传到overleaf的目录 &#xff08;3&#xff09;在文中添加相应代码 三…...

JSON格式Python,Java,PHP等封装根据关键词搜索获取淘宝商品列表数据API

淘宝是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要用关键词搜索获取淘宝天猫商品列表&#xff0c;您可以通过开放平台的接口或者直接访问淘宝天猫商城的网页来获取商品列表详细信息。以下是两种常用方法的介绍&a…...

MySQL MHA高可用配置及故障切换

文章目录 一.MySQL MHA1.什么是MHA&#xff12;.&#xff2d;&#xff28;&#xff21;的组成&#xff12;.&#xff11;MHA Node (数据节点)&#xff12;.&#xff12;MHA Manager (管理节点) &#xff13;.&#xff2d;&#xff28;&#xff21;的特点&#xff14;.&#xf…...

PHP8知识详解:PHP8开发工具VS Code的安装

作为PHP8的开发工具有很多&#xff0c;具有IDE功能的有phpstorm、Visual Studio Code、Sublime Text、NetBeans、Eclipse、Codelobster、PHP Designer等&#xff0c;当然还有很多轻量的工具&#xff0c;比如Notepad、Editplus等。本文给你介绍的是万能编辑器Visual Studio Code…...

Sui Move与标准Move的有哪些区别和根本性创新

Sui网络将Sui Move作为其本地编程语言&#xff0c;使用Sui Move编写的apps利用Sui的共识机制&#xff0c;实现了令人印象深刻的交易性能。 然而&#xff0c;熟悉Move编程语言的开发者在探索Sui文档时可能会感到困惑&#xff0c;因为该文档着重介绍了对象和一些指令&#xff0c…...

构建自己的ChatGPT:从零开始构建个性化语言模型

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…...

【react】react18的学习(十二)– 底层原理(二)之 迭代器 iterator

迭代器iterator 是一种 ES6 规范&#xff0c;具有这种机制的数据结构才可以使用for of循环&#xff1a;返回每一项的值&#xff1b; 原型链具有Symbol.iterator属性的数据结构都具备&#xff1b;如数组、部分类数组、字符串等&#xff1b; 普通对象就不能用&#xff1b; for-…...

一遍过JavaSE基础知识

文章目录 前言安装Java Development Kit (JDK)安装jdk配置开发环境验证是否安装配置成功 编写第一个Java程序hello world运行Java程序的流程 数据类型和变量数据类型变量 程序逻辑控制条件语句循环语句跳转语句 数组声明和创建数组访问数组元素数组长度遍历数组多维数组 面向对…...

【云原生】Kubernetes之ConfigMap

ConfigMap ConfigMap 是一种 API 对象&#xff0c;用来将非机密性的数据保存到键值对中。使用时&#xff0c; Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件 ConfigMap 将你的环境配置信息和 容器镜像 解耦&#xff0c;便于应用配置的修改 说明&#xff1a;…...

8.python设计模式【组合模式】

内容&#xff1a;将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。角色&#xff1a; 抽象组建&#xff08;component&#xff09;叶子组建(Leaf)复合组建(Composite)客户端 (Client) UML 图 举个例子 需求&#xf…...

tkinter制作任意图形窗口

import tkinter from PIL import Image, ImageTkdog tkinter.Tk() # 设置图片描绘的坐标&#xff0c;注意乘号是字母x dog.geometry(500x500200100) # 不允许修改大小 dog.resizable(False, False) # 不显示标题栏 dog.overrideredirect(True) # 设置白色透明色&#xff0c;这…...

视频监控综合管理平台EasyCVR多分屏默认播放协议的配置优化

视频监控综合管理平台EasyCVR具备视频融合汇聚能力&#xff0c;TSINGSEE青犀视频平台基于云边端一体化架构&#xff0c;可支持多协议、多类型设备接入&#xff0c;包括&#xff1a;NVR、IPC、视频编码器、无人机、车载设备、智能手持终端、移动执法仪等。国标GB28181视频平台Ea…...

2023杭电多校第三场 1012.Noblesse Code

传送门:Vjudge 前题提要:一道挺有意思的数论题.赛时对于这道题没什么想法,但是赛后细品之后其实感觉也就那么一回事.但是这种 更相损减术与辗转相除法 相转化的题目还是有点典的,需要好好消化一下. 首先看完题目.我们需要考虑的是 ( A , B ) (A,B) (A,B)与 ( a , b ) (a,b) (…...

ubuntu qt 环境变量配置

ubuntu设置qt环境变量 qt 安装路径为&#xff1a;/home/ljn/Qt5.12 包含bin等目录的路经&#xff1a;/home/ljn/Qt5.14.2/5.14.2/gcc_64 环境变量配置 打开配置文件&#xff1a; sudo gedit /etc/profile在底部添加&#xff1a; export PATH"/home/ljn/Qt5.14.2/Tool…...

按照Vue写WPF(0):功能实现

文章目录 前言VUE具有的功能如何专业到WPF上面 前言 我最近学了WPF之后我终于知道为什么WPF学习曲线那么陡峭了。因为WPF没有组件化的思想&#xff0c;或者说没有按照Vue一样去模板化开发。 为什么我推荐Vue的想法呢。因为Vue最大的特点就是模板化&#xff0c;让Vue工程师去写…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...