我是靠谱客的博主 谦让小松鼠,最近开发中收集的这篇文章主要介绍springboot上传文件的几种情况代码实现和可能存在的问题(01、只上传且上传一个文件 02、只上传且上传多个文件 03、上传文件的同时还提交其他文本信息),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

本文主要介绍下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、上传文件的同时还提交其他文本信息)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部