概述
本文主要介绍下springboot上传文件的几种情况的代码实现和可能存在的问题(废话不多说,主要以代码为导向同时结合存在的问题,中间会简单掺杂一些上传文件时http协议的报文结构、内容分析说明),主要分以下几种情况(注意一定要从上往下按顺序看,一些关键细节在上面篇章如果介绍过,后面就不再赘述,比如:报错了如何解决、http报文结构的简单说明,如果需要了解各种http请求报文结构可以查看https://blog.csdn.net/mayunju/article/details/113867033):
01、只上传且上传一个文件
01-01、使用MultipartFile直接接收文件参数
01-02、使用一个变量接收参数(变量中使用MultipartFile的实现类CommonsMultipartFile来接收文件参数)
02、只上传且上传多个文件
02-01、使用MultipartFile[]直接接收文件参数
02-02、使用一个变量接收参数(变量中使用MultipartFile的实现类CommonsMultipartFile[]来接收文件参数)
03、上传文件的同时还提交其他文本信息(适用于上传文件的同时还提交其它表单信息等类似场景)
03-01、上传单个文件同时还提交其他文本信息
03-02、上传多个文件同时还提交其他文本信息
用到的工具:idea、postman、Fiddler(Windows平台抓包工具)
一、首先创建一个空的springboot项目,创建成功后结构如下:
pom.xml的核心内容如下(不贴任何多余的内容,下面其他部分亦如此):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
</parent>
<groupId>com.example</groupId>
<artifactId>springboot-upload-file</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-upload-file</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
application.yml的内容如下:
server:
port: 8080
servlet:
context-path: /springboot-upload-file
二、接下来是核心部分
首先创建一个Controller,后面的示例都写在这一个Controller中:
package com.example.springbootuploadfile.uploadfile;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/")
public class UploadFileDemoController {
}
01、只上传且上传一个文件
01-01、使用MultipartFile直接接收参数(org.springframework.web.multipart.MultipartFile)
后台代码部分(主要是接收参数这块儿,@RequestParam("newFile")这里要注意,和前端传参要保持一致,也可以不加该注解,默认和参数名uploadFile一致,后面不再赘述)
/**
* 单文件上传(只上传文件,不提交其他文本信息)
*/
@PostMapping("/uploadSingleFile")
public String uploadSingleFile(@RequestParam("newFile") MultipartFile uploadFile) {
// 文件上传的路径
String uploadBasePath = "D:\uploadFile";
File file = new File(uploadBasePath);
if (!file.isDirectory()) {
file.mkdirs();
}
// 文件原名,包括后缀
String oldName = uploadFile.getOriginalFilename();
// 文件新名,包括后缀
String newName = "newFileName" + oldName.substring(oldName.indexOf("."));
try {
uploadFile.transferTo(new File(file, newName));
// 文件全路径(包括文件名.后缀)
String path = file.getPath() + "\" + newName;
return path;
} catch (IOException e) {
e.printStackTrace();
}
return "上传失败";
}
前端部分(这里以postman为例,后面不再赘述,红线圈住的部分为重点)
Fiddler抓包(这里主要是从http请求报文结构的角度出发,红线圈住的部分为重点,后面不再赘述,这里也不会详解,后面会单独写一篇http协议请求报文结构分析)
01-02、使用一个变量接收参数(变量中使用MultipartFile的实现类CommonsMultipartFile来接收文件参数)
首选创建一个用于controller层接收参数的类:
package com.example.springbootuploadfile.param;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
public class SingleUploadParam {
private CommonsMultipartFile uploadFile;
public CommonsMultipartFile getUploadFile() {
return uploadFile;
}
public void setUploadFile(CommonsMultipartFile uploadFile) {
this.uploadFile = uploadFile;
}
}
后台代码部分:
/**
* 单文件上传(只上传文件,不提交其他文本信息)
*/
@PostMapping("/uploadSingleFile1")
public String uploadSingleFile1(SingleUploadParam uploadParam) {
// 文件上传的路径
String uploadBasePath = "D:\uploadFile";
File file = new File(uploadBasePath);
if (!file.isDirectory()) {
file.mkdirs();
}
// 获取上传的文件
MultipartFile uploadFile = uploadParam.getUploadFile();
// 文件原名,包括后缀
String oldName = uploadFile.getOriginalFilename();
// 文件新名,包括后缀
String newName = "newFileName" + oldName.substring(oldName.indexOf("."));
try {
uploadFile.transferTo(new File(file, newName));
// 文件全路径(包括文件名.后缀)
String path = file.getPath() + "\" + newName;
return path;
} catch (IOException e) {
e.printStackTrace();
}
return "上传失败";
}
前端部分(这里以postman为例)
如果你按照这个教程看到这里,按上面一步一步来的话,会发现这里会出一个异常,内容如下:
java.lang.ClassNotFoundException: org.apache.commons.fileupload.FileItem
at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_261]
at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_261]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355) ~[na:1.8.0_261]
at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[na:1.8.0_261]
at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.8.0_261]
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[na:1.8.0_261]
at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[na:1.8.0_261]
at
这个问题,加入以下依赖即可:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
此时如果你继续上传文件,不会有上面那个异常了,但是还会有新的一样,如下所示:
Field error in object 'singleUploadParam' on field 'uploadFile': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@5e4f36af];
codes [typeMismatch.singleUploadParam.uploadFile,typeMismatch.uploadFile,typeMismatch.org.springframework.web.multipart.commons.CommonsMultipartFile,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [singleUploadParam.uploadFile,uploadFile]; arguments [];
default message [uploadFile]];
default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'org.springframework.web.multipart.commons.CommonsMultipartFile' for property 'uploadFile';
nested exception is java.lang.IllegalStateException: Cannot convert value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type
'org.springframework.web.multipart.commons.CommonsMultipartFile' for property 'uploadFile': no matching editors or conversion strategy found]]
创建下面这个类即可解决:
package com.example.springbootuploadfile.config;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
@Configuration
@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
public class CommonMultipartConfig {
@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
return resolver;
}
}
此时再上传即可成功,Fiddler抓包:
02、只上传且上传多个文件
02-01、使用MultipartFile[]直接接收文件参数
后台代码部分:
/**
* 多文件上传(只上传文件,不提交其他文本信息)
*/
@PostMapping("/uploadMultFile")
public String uploadMultFile(@RequestParam("newFile") MultipartFile[] uploadFiles) {
// 文件上传的路径
String uploadBasePath = "D:\uploadFile";
File file = new File(uploadBasePath);
if (!file.isDirectory()) {
file.mkdirs();
}
// 当前上传成功的第几个文件
int i = 1;
for (MultipartFile uploadFile : uploadFiles) {
// 文件原名,包括后缀
String oldName = uploadFile.getOriginalFilename();
// 文件新名,包括后缀
String newName = "newFileName" + i + oldName.substring(oldName.indexOf("."));
try {
uploadFile.transferTo(new File(file, newName));
i ++;
} catch (IOException e) {
e.printStackTrace();
}
}
return "上传成功";
}
前端部分(postman):
Fiddler抓包(红线圈住部分为重点!!!!,下面这个是多文件的http请求报文,重点!!!!!!!!,贴了3张图,从上往下是连续的):
02-02、使用一个变量接收参数(变量中使用MultipartFile的实现类CommonsMultipartFile[]来接收文件参数)
首先创建一个用于接收参数的类:
package com.example.springbootuploadfile.param;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
public class MultUploadParam {
private CommonsMultipartFile[] uploadFile;
public CommonsMultipartFile[] getUploadFile() {
return uploadFile;
}
public void setUploadFile(CommonsMultipartFile[] uploadFile) {
this.uploadFile = uploadFile;
}
}
Controller部分如下:
/**
* 多文件上传(只上传文件,不提交其他文本信息)
*/
@PostMapping("/uploadMultFile1")
public String uploadMultFile1(MultUploadParam multUploadParam) {
// 文件上传的路径
String uploadBasePath = "D:\uploadFile";
File file = new File(uploadBasePath);
if (!file.isDirectory()) {
file.mkdirs();
}
// 获取上传的文件
MultipartFile[] uploadFiles = multUploadParam.getUploadFile();
// 当前上传成功的第几个文件
int i = 1;
for (MultipartFile uploadFile : uploadFiles) {
// 文件原名,包括后缀
String oldName = uploadFile.getOriginalFilename();
// 文件新名,包括后缀
String newName = "newFileName" + i + oldName.substring(oldName.indexOf("."));
try {
uploadFile.transferTo(new File(file, newName));
i ++;
} catch (IOException e) {
e.printStackTrace();
}
}
return "上传成功";
}
前端部分(postman):
03、上传文件的同时还提交其他文本信息
03-01、上传单个文件同时还提交其他文本信息
首先创建一个类,如下所示:
package com.example.springbootuploadfile.param;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
public class SingleUploadParam1 {
/**
* 其它信息
*/
private String otherColumn;
/**
* 单个文件
*/
private CommonsMultipartFile uploadFile;
public String getOtherColumn() {
return otherColumn;
}
public void setOtherColumn(String otherColumn) {
this.otherColumn = otherColumn;
}
public CommonsMultipartFile getUploadFile() {
return uploadFile;
}
public void setUploadFile(CommonsMultipartFile uploadFile) {
this.uploadFile = uploadFile;
}
}
Controller部分代码:
/**
* 单文件上传(上传文件的同时提交其他文本信息)
*/
@PostMapping("/uploadSingleFile2")
public String uploadSingleFile2(SingleUploadParam1 uploadParam) {
// 文件上传的路径
String uploadBasePath = "D:\uploadFile";
File file = new File(uploadBasePath);
if (!file.isDirectory()) {
file.mkdirs();
}
// 获取上传的文件
MultipartFile uploadFile = uploadParam.getUploadFile();
// 文件原名,包括后缀
String oldName = uploadFile.getOriginalFilename();
// 文件新名,包括后缀
String newName = "newFileName" + oldName.substring(oldName.indexOf("."));
try {
uploadFile.transferTo(new File(file, newName));
// 返回一下其它文本信息,表示收到了除文件外的其他传参
return uploadParam.getOtherColumn();
} catch (IOException e) {
e.printStackTrace();
}
return "上传失败";
}
前端部分(postman):
抓包(这里很关键,要看一下,特别是请求头的content-type以及请求体里面的内容,文件和其他的文本的在请求体里面的结构):
03-02、上传多个文件同时还提交其他文本信息
首先创建一个类,如下所示:
package com.example.springbootuploadfile.param;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
public class MultUploadParam1 {
/**
* 其它信息
*/
private String otherColumn;
/**
* 多个文件
*/
private CommonsMultipartFile[] uploadFile;
public String getOtherColumn() {
return otherColumn;
}
public void setOtherColumn(String otherColumn) {
this.otherColumn = otherColumn;
}
public CommonsMultipartFile[] getUploadFile() {
return uploadFile;
}
public void setUploadFile(CommonsMultipartFile[] uploadFile) {
this.uploadFile = uploadFile;
}
}
controller部分:
/**
* 多文件上传(上传文件的同时提交其他文本信息)
*/
@PostMapping("/uploadMultFile2")
public String uploadMultFile2(MultUploadParam1 multUploadParam) {
// 文件上传的路径
String uploadBasePath = "D:\uploadFile";
File file = new File(uploadBasePath);
if (!file.isDirectory()) {
file.mkdirs();
}
// 获取上传的文件
MultipartFile[] uploadFiles = multUploadParam.getUploadFile();
// 当前上传成功的第几个文件
int i = 1;
for (MultipartFile uploadFile : uploadFiles) {
// 文件原名,包括后缀
String oldName = uploadFile.getOriginalFilename();
// 文件新名,包括后缀
String newName = "newFileName" + i + oldName.substring(oldName.indexOf("."));
try {
uploadFile.transferTo(new File(file, newName));
i ++;
} catch (IOException e) {
e.printStackTrace();
}
}
// 返回一下其它文本信息,表示收到了除文件外的其他信息
return multUploadParam.getOtherColumn();
}
前端部分(postman):
抓包部分(很关键看一下):
写到这里就算结束了,最好说明一点,上传文件的同时又上传文本信息,很多同学可能看到之后会联想(我这么猜的,特别是新手),有的同学因为工作的惯性,会用到一个@RequestBody的注解,又看到我这里写的上传文件同时上传文本的示例,接收参数也是一个类似实体类吧,就会把@RequestBody这个注解加上,这样是接收不到参数的(具体原因看抓包部分的报文结构就明白了)。如果用@RequestBody注解标识的实体类来接收参数的话,传参是不能像我这样传参的(参考postman部分),这种场景也不是上传文件的场景。
最后
以上就是谦让小松鼠为你收集整理的springboot上传文件的几种情况代码实现和可能存在的问题(01、只上传且上传一个文件 02、只上传且上传多个文件 03、上传文件的同时还提交其他文本信息)的全部内容,希望文章能够帮你解决springboot上传文件的几种情况代码实现和可能存在的问题(01、只上传且上传一个文件 02、只上传且上传多个文件 03、上传文件的同时还提交其他文本信息)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复