@MultipartConfig注解
前言:
在学习Javaweb的Servlet文件上传和下载的过程中,我们会遇到一个特殊的注解---@MultipartConfig。
@MultipartConfig的适用情况:
1.文件上传: 当您的应用程序需要接收用户上传的文件时,可以在相应的 Servlet 上使用 @MultipartConfig 注解。通过使用该注解Servlet 可以方便地解析和处理 multipart/form-data 类型的请求,从中提取上传的文件。
2.图片上传: 如果您的应用程序需要用户上传图片,例如头像、照片等,那么您可以使用 @Multipartconfig 注解来处理包含图片文件的表单请求。
3.多媒体内容:如果您的应用程序需要处理包含音频、视频或其他多媒体内容的表单请求,您可以使用 @Multipartconfig 注解来处理这些请求并提取相应的多媒体文件。
4.表单中的大量数据:有时,表单中可能包含大量的字段和数据。在这种情况下,@Multipartconfig 注解可以帮助您处理这些复杂的表单请求。
以上也许您不想花大量的时间来阅读,那么我就用一句简单的话来解释:
当您的应用程序需要处理包含文件或其他二进制数据的表单请求时,可以使用 @MultipartConfig
注解。它使得解析和处理 multipart/form-data
请求变得更加简单和方便。
了解完@MultipartConfig注解的适用情况。接下来还是来看看API文档的描述吧。
API文档内容:
翻译过来就是:
@MultipartConfig
注解可以应用于 Servlet 类上,用于指示该 Servlet 预期符合 multipart/form-data
MIME 类型的请求。这通常用于处理包含文件上传的表单数据。
当一个 Servlet 使用了 @MultipartConfig
注解后,它可以通过调用 getPart
或 getParts
方法来获取给定 multipart/form-data
请求的各个部分(Part 组件)。Part 组件代表了上传的文件或其他表单字段的数据。
当然,这个注解还有一些属性,如下:
这里不过多展开这些属性,只需要知道它有这几个属性:
1.fileSizeThreshold
(文件大小阈值):指定文件在超过该大小阈值后将被写入磁盘
2.location
(文件存储目录):指定文件将存储的目录位置。上传的文件将被存储在该指定的目录中
3.maxFileSize
(最大文件大小):指定允许上传的单个文件的最大大小
4.maxRequestSize
(最大请求大小):指定允许的 multipart/form-data 请求的最大大小。
实例测试:
那么还是先来看一下正常的代码与运行结果吧!
<!doctype html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><link href = "Book_entry.css" rel="stylesheet" type = "text/css" /><title>图书录入系统</title>
</head>
<body>
<!--书籍名称、出版社、编者、价格、书籍介绍--><h2>图书录入</h2>
<div><form enctype="multipart/form-data" method="post" action="../Book_entry"><label for = "book_name">书籍名称: </label><br><input type = "text" id = "book_name" name = "book_name" placeholder="请输入书籍名称"><br><br><label for = "publishing_house">出版社: </label><br><input type = "text" id = "publishing_house" name = "publishing_house" placeholder="请输入出版社"><br><br><label for = "editor">编者: </label><br><input type = "text" id = "editor" name = "editor" placeholder="请输入编者"><br><br><label for = "Price">价格: </label><br><input type = "text" id = "Price" name = "Price" placeholder="请输入价格"><br><br><p><input type="checkbox" value = "social_science" name = "Book_type" checked/>社会科学<input type="checkbox" value = "natural_science" name = "Book_type" />自然科学<input type="checkbox" value = "philosophy" name = "Book_type" />哲学<input type="checkbox" value = "novel" name = "Book_type" />小说<input type="checkbox" value = "art" name = "Book_type" />艺术</p><label>书籍介绍: </label><br><textarea name="description"></textarea><br><br><input type = "file" id = "photo" name = "photo" placeholder="请插入图片"><input type="submit" value="提交"></form>
</div></body>
</html>
package com.example;import com.example.Book;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;@MultipartConfig
@WebServlet("/Book_entry")public class BookServlet extends HttpServlet {private List<Book> books = new ArrayList<>();@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding("utf-8");// 从请求参数中获取书籍信息String book_name = request.getParameter("book_name");String publishing_house = request.getParameter("publishing_house");String editor = request.getParameter("editor");String Price = request.getParameter("Price");String bookType = request.getParameter("Book_type");String description = request.getParameter("description");//获取上传的Part对象Part photo = request.getPart("photo");StringBuffer sb = new StringBuffer();if(book_name.isBlank())sb.append("必须输入书名");else if(publishing_house.isBlank())sb.append("必须输入出版社");else if(editor.isBlank())sb.append("必须输入作者");else if(Price.isBlank())sb.append("必须输入价格");else if(bookType.isBlank())sb.append("必须输入书的类型");else if(description.isBlank())sb.append("必须输入书籍介绍");else if(photo == null)sb.append("必须上传书的封面");// if(sb.length() != 0)
// {
// response.getWriter().println(sb);
// return;
// }
// sb.append("书名:").append(book_name).append("<br>");
// sb.append("出版社:").append(publishing_house).append("<br>");
// sb.append("作者:").append(editor).append("<br>");
// sb.append("价格:").append(Price).append("<br>");
// sb.append("书类型:").append(bookType).append("<br>");
// sb.append("书籍介绍:").append(description).append("<br>");//断言assert photo != null;InputStream is = photo.getInputStream();ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] b = new byte[1024];while(is.read(b)>0){baos.write(b);}b = baos.toByteArray();UUID uuid = UUID.randomUUID();String sfn = photo.getSubmittedFileName();String suffix = sfn.substring(sfn.lastIndexOf("."));FileOutputStream fos = new FileOutputStream("D:/photo/" + uuid.toString() + suffix);fos.write(b);fos.close();String imageUrl = "D:/photo/" + uuid.toString() + suffix;// 创建Book对象Book book = new Book();book.setTitle(book_name);book.setPublisher(publishing_house);book.setEditor(editor);book.setPrice(Price);book.setDescription(description);// 将书籍信息添加到列表中books.add(book);// 返回成功信息response.setContentType("text/html;charset=utf-8");response.getWriter().println(sb);String head = """<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>图书信息</title><link href = "./Book_entry.css" rel="stylesheet" type = "text/css"/></head><body>""";head += "<h3 style=\"text-align:center\">图书信息</h3>";head += "<div>";head += "<p>书名:" + book_name + "</p>";head += "<p>出版社:" + publishing_house + "</p>";head += "<p>编辑:" + editor + "</p>";head += "<p>价格:" + Price + "</p>";head += "<p>书籍类型:" + bookType + "</p>";head += "<p>描述:" + description + "</p>";head += "<img src=\"D:/photo/" + uuid.toString() + suffix + "\" alt=\"书籍封面\">";head += "</div>";response.getWriter().println(head);}
}
以上便是代码部分
那么来看一下运行的结果!
代码是正常运行的!
但是!!!如果我们去掉@MultipartConfig的注解呢?
我们发现:从html页面获取的内容为null
调试结果也告诉我们:book_name为空了
那么原因如下:
如果你在处理包含文件上传的multipart/form-data
类型的请求时没有添加@MultipartConfig
注解,request.getParameter()
方法无法直接获取文本框(<input type="text">
)中的内容,而会返回null
。
这是因为在multipart/form-data
类型的请求中,表单数据包含了文件和其他文本字段,而request.getParameter()
方法只能用于获取application/x-www-form-urlencoded
编码类型的表单参数值,不能直接获取multipart/form-data
类型请求中的文本字段的值。
当使用@MultipartConfig
注解配置Servlet来处理multipart/form-data
请求时,Servlet容器会根据该注解的配置,自动解析请求中的文件和文本字段,并将它们作为Part
对象提供给开发者使用。
要获取multipart/form-data
请求中的文本字段的值,你可以使用request.getPart()
方法来获取对应的Part
对象,然后通过Part
对象的getInputStream()
方法读取文本字段的内容。
相关文章:

@MultipartConfig注解
前言: 在学习Javaweb的Servlet文件上传和下载的过程中,我们会遇到一个特殊的注解---MultipartConfig。 MultipartConfig的适用情况: 1.文件上传: 当您的应用程序需要接收用户上传的文件时,可以在相应的 Servlet 上使用 Multipart…...

Python并发编程简介
1、Python对并发编程的支持 多线程: threading, 利用CPU和IO可以同时执行的原理,让CPU不会干巴巴等待IO完成多进程: multiprocessing, 利用多核CPU的能力,真正的并行执行任务异步IO: asyncio,在单线程利用CPU和IO同时执行的原理,实现函数异步执行使用Lo…...

WebSocket介绍及部署
WebSocket是一种在单个TCP连接上进行全双工通信的协议,其设计的目的是在Web浏览器和Web服务器之间进行实时通信(实时Web)。 WebSocket协议的优点包括: 1. 更高效的网络利用率:与HTTP相比,WebSocket的握手…...

自动求导,计算图示意图及pytorch实现
pytorch实现 x1 torch.tensor(3.0, requires_gradTrue) y1 torch.tensor(2.0, requires_gradTrue) a x1 ** 2 b 3 * a c b * y1 c.backward() print(x1.grad) print(y1.grad) print(x1.grad 6 * x1 * y1) print(y1.grad 3 * (x1 ** 2))输出为: tensor(36.) …...

睿伴科创上线了
Robotutor睿伴,一个专业的青少儿编程科创教育品牌和科创服务平台。 Robotutor睿伴拥有一个超过5年的青少儿编程科创教育团队,积累了丰富的课程研发,教学服务和赛事辅导经验。并和上海多所知名高校、上海市计算机学会、上海青少年科学社等开展…...

域名抢注和域名注册
随着互联网的发展,域名已经成为了企业和个人在网络上展示自己的重要标志。如何获得一段好记、易拼写、有意义的域名,是很多人都面临的问题。本文将介绍域名抢注和域名注册的相关内容,并推荐ym.qqmu.com这个可靠的域名注册平台。 一、什么是域…...

【20】c++设计模式——>组合模式
组合模式定义 C组合模式(Composite Pattern)是一种结构型设计模式,他允许将对象组合成树形结构来表示“部分-整体”的层次结构;在组合模式中有两种基本类型的对象:叶子对象和组合对象,叶子对象时没有子对象…...

Jetpack:004-如何使用文本组件
文章目录 1. 概念介绍2. 使用方法2.1 通用参数2.2 专用参数 3. 示例代码4. 内容总结 我们在上一章回中介绍了Jetpack组件在布局中的对齐方式,本章回中主要介绍文 本组件的使用方法。闲话休提,让我们一起Talk Android Jetpack吧 1. 概念介绍 我们在本章…...

JVM(八股文)
目录 一、JVM简介 二、JVM中的内存区域划分 三、JVM加载 1.类加载 1.1 加载 1.2 验证 1.3 准备 1.4 解析 1.5 初始 1.6 总结 2.双亲委派模型 四、JVM 垃圾回收(GC) 1.确认垃圾 1.1 引用计数 1.2 可达性分析(Java 采用的方案&a…...

C#WPF标记扩展应用实例
本文介绍C#WPF标记扩展应用实例 一、标记扩展 标记扩展是一个 XAML 语言概念。 用于提供特性语法的值时,大括号({ 和 })表示标记扩展用法。 此用法指示 XAML 处理不要像通常那样将特性值视为文本字符串或者可转换为字符串的值。就是类似于值用变量的意思。 WPF 应用编程中…...

四维曲面如何画?matlab
clc; clear all [theta,phi]meshgrid(linspace(0,pi,50),linspace(0,2*pi,50)); zcos(theta); xsin(theta).*cos(phi); ysin(theta).*sin(phi); f-1*((x.*y).2(y.*z).2(z.*x).^2); surf(sin(theta).*cos(phi).*f,sin(theta).*sin(phi).*f,cos(theta).*f,f) 结果...

软件培训测试高级工程师多测师肖sir__html之作业11
html之作业 案例1: 截图: 代码: <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>表单</title></head><body><table style"background-color:red" bo…...

详解一典型的反激式开关电源方案
理解一个单端反激式开关电源方案: 1、抛出问题: 如图,在某系统方案上看到下图所示的单端反激式开关电源方案。 2、解析问题: 2.1、乍一看: 典型的AC-DC电路,考虑了安规及过压过流保护,如&am…...

AI 大框架基于python来实现基带处理之TensorFlow(信道估计和预测模型,信号解调和解码模型)
AI 大框架基于python来实现基带处理之TensorFlow(信道估计和预测模型,信号解调和解码模型) 基带处理(Baseband Processing)是一种信号处理技术,用于在通信系统中处理和调制基带信号。基带信号是指未经过调制的信号,通常包含原始数…...

阿里云上了新闻联播
我是卢松松,点点上面的头像,欢迎关注我哦! 阿里新任的CEO吴泳铭上央视新闻联播了! 在昨天的新闻联播里,出席科技座谈会,有一个特别镜头,出现了阿里新任CEO吴泳铭的镜头。 这个信号意义明显,我…...

算法练习12——跳跃游戏
LeetCode 55 跳跃游戏 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 贪…...

Java架构师系统架构设计服务拆分
目录 1 服务拆分和子系统模块拆分1.1 服务化架构的优势2 描绘系统蓝图里面的详解服务2.1 为什么拆分服务3 服务拆分的基本要求3.1 服务功能是自包含的3.2 服务呢应该具备独立性和专业性3.3 服务是无状态的3.4 服务之间采用轻量级的通讯机制4 服务拆分的基本方法4.1 按业务边界拆…...

通用任务批次程序模板
通用批次任务模板 我们总会遇到需要使用批次任务处理问题的场景,任务有很多不同类型的任务,同时这些任务可能都有大致相同,甚至抽象出来共同的执行阶段状态。 任务的执行肯定无法保证一帆风顺,总会在某个时间阶段被打断ÿ…...

Rust专属开发工具——RustRover发布
JetBrains最近推出的Rust集成开发工具——RustRover已经发布,官方网站:RustRover: Rust IDE by JetBrains JetBrains出品过很受欢迎的开发工具IntelliJ IDEA、PyCharm等。 RustRover优势 Rust集成环境,根据向导可自动下载安装rust开发环境提…...

数据结构:链表(1)
顺序表的优缺点 缺点: 1.插入数据必须移动其他数据,最坏情况下,就是插入到0位置。时间复杂度O(N) 2.删除数据必须移动其他数据,最坏情况下,就是删除0位置。时间复杂度O(N) 3.扩容之后,有可能会浪费空间…...

软件测试之概念篇2(瀑布模型、螺旋模型、增量模型和迭代模型、敏捷模型,V模型、W模型)
目录 开发模型 (1)瀑布模型 (2)螺旋模型 (3)增量模型和迭代模型 (4)敏捷模型 (5)测试模型(V模型、W模型) V模型 W模型 开发模型…...

【【萌新的SOC学习之重新起航SOC】】
萌新的SOC学习之重新起航SOC ZYNQ PL 部分等价于 Xilinx 7 系列 FPGA PS端:Zynq 实际上是一个以处理器为核心的系统,PL 部分可以看作是它的一个外设。 我们可以通过使用AXI(Advanced eXtensible Interface)接口的方式调用 IP 核,系统通过 AX…...

ElasticSearch 学习7 集成ik分词器
网上找了一大堆,很多都介绍的不详细,开始安装完一直报错找不到plugin-descriptor.properties,有些懵这个东西不应该带在里面吗,参考了一篇博客说新建一个这个,新建完可以启动,但是插入索引数据会报错找不到…...

[NewStarCTF 2023 公开赛道] week1
最近没什么正式比赛,都是入门赛,有moectf,newstar,SHCTF,0xGame都是漫长的比赛。一周一堆制。 这周newstar第1周结束了,据说py得很厉害,第2周延期了,什么时候开始还不一定,不过第一周已经结束提交了&#…...

ThreeJS-3D教学六-物体位移旋转
之前文章其实也有涉及到这方面的内容,比如在ThreeJS-3D教学三:平移缩放物体沿轨迹运动这篇中,通过获取轨迹点物体动起来,其它几篇文章也有旋转的效果,本篇我们来详细看下,另外加了tween.js知识点࿰…...

BC v1.2充电规范
1 JEITA Reference to https://www.mianbaoban.cn/blog/post/169964 符合 JEITA 规范的锂离子电池充电器解决方案 2 Battery Fuel Gauge 2.1 Cycle Count(充放电循环次数) 此指令回传一只读字段,代表电芯组已经历的完整充放电循环数。当放电容…...

判断一个整数是否回文
回文数字的定义:第一位和最后一位相等,第二位和倒数第二位相等...依次类推,比如1221,12321等等,也就是说一个数字如果是回文,那么将它反转之后,一定和原来的值相等 解法一:投机取巧,…...

【广州华锐互动】车辆零部件检修AR远程指导系统有效提高维修效率和准确性
在快速发展的科技时代,我们的生活和工作方式正在被重新定义。这种变化在许多领域都有所体现,尤其是在汽车维修行业。近年来,AR(增强现实)技术的进步为这个行业带来了前所未有的可能性。通过将AR技术与远程协助系统相结…...

简单实现接口自动化测试(基于python+unittest)
简介 本文通过从Postman获取基本的接口测试Code简单的接口测试入手,一步步调整优化接口调用,以及增加基本的结果判断,讲解Python自带的Unittest框架调用,期望各位可以通过本文对接口自动化测试有一个大致的了解。 引言 为什么要…...

【算法|双指针系列No.4】leetcode11. 盛最多水的容器
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望…...