SpringBoot实现文件的上传以及表单数据的同时提交

SpringBoot实现文件以及表单数据的上传

一、前期准备

yml文件

 spring:
   servlet:
    multipart:
      max-file-size: 10MB  #文件上传的最大大小
      file-size-threshold: 10MB

pom文件

    <!--文件的上传下载-->
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

二、前端页面

通过表单传递图片文件的同时上传表单中的数据

 <form method="post" class="form-x" enctype="multipart/form-data" id="registerForm">
                            <!--教练-->
                            <div class="form-group">

                                <div class="label">
                                    <label>球队名称:</label>
                                </div>
                                <div class="field">
                                    <input id="teamName" type="text" class="input w50" value="" name="name"
                                           placeholder="请输入4-6位汉字"/>
                                    <div class=""><span style="margin-left: 30px;color:red" hidden="hidden"
                                                        id="warn"></span></div>
                                </div>

                            </div>
                            <!--球队队标-->
                            <div class="form-group">
                                <div class="label">
                                    <label>球队队标:</label>
                                </div>
                                <div class="field">
                                    <input id="teamLog" type="file" accept="image/png, image/jpeg" name="file"
                                           class="input tips" style="width:25%; float:left;" placeholder="仅支持png或jpg格式"
                                           value=""/>
                                </div>
                            </div>
                            <!--球队简介-->
                            <div class="form-group">
                                <div class="label">
                                    <label>球队简介:</label>
                                </div>
                                <div class="field">
                                    <textarea id="teamIntroduce" class="input" name="intro" style=" height:90px;"
                                              placeholder="请介绍一下自己球队"></textarea>
                                    <div class="tips"></div>
                                </div>
                            </div>
                            <!--球队教练-->
                            <div class="form-group">
                                <div class="label">
                                    <label>球队教练:</label>
                                </div>
                                <div class="field">
                                    <input id="coachName" type="text" class="input w50" name="coach" value=""/>
                                    <div class="tips"></div>
                                </div>
                            </div>
                            <!--队伍人数-->
                            <div class="form-group">
                                <div class="label">
                                    <label>队伍人数:</label>
                                </div>
                                <div class="field">
                                    <input id="memberNumber" type="text" class="input w50" name="memberNumber" value=""
                                           placeholder="球队建队人数不能低于12人"/>
                                    <div class="tips"></div>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="label">
                                    <label></label>
                                </div>
                                <div class="field">
                                    <div style="padding:30px;">
                                        <input type="button" class="button button-block bg-main text-big input-big" onclick="clickMe();"
                                               id="apply-button"
                                               value="申请">
                                    </div>
                                </div>
                            </div>
                        </form>

效果图

SpringBoot实现文件的上传以及表单数据的同时提交

使用Ajax提交表单到后台

重点是使用了jQuery使用FormData对象上传文件。

FormData的主要用途有两个:
1、将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。
2、异步上传文件

创建一个空对象:
var formdata=new FormData();  //通过FormData构造函数创建一个空对象
formdata.append("name","laotie");  //可以通过append()方法来追加数据
console.log(formdata.get("name"));  //通过get方法对值进行读取 laotie
formdata.set("name","laoliu");  //通过set方法对值进行设置
console.log(formdata.get("name"));  //laoliu

更多详细 参见 https://developer.mozilla.org/zh-CN/docs/Web/API/FormData

可能出现的问题

sp报Unsupported Media Type Content type '*/*;charset=UTF-8' not supported

ajax默认:Content-Type: application/x-www-form-urlencoded;charset=utf-8
解决:前端ajax提交json数据时  contentType:application/json

JS代码

<script>
        function clickMe() {
            var form = document.getElementById("registerForm"),//先获到表单的JQ对象
                formData = new FormData(form);
            $.ajax({
                url: "/teamRegister",
                type: "post",
                data: formData,
                processData: false, 
                contentType: false, //contentType设置为false。因为是由<form>表单构造的FormData对象,且已经声明了属性enctype="multipart/form-data",所以这里设置为false。
                success: function (data) {
                    alert("success!!")
                },
                error: function () {
                    alert("failure!!")
                }
            })
        }
    </script>
    

表单中的提交方式要设置为post 必须添加 enctype="multipart/form-data"
   例如 <form method="post" enctype="multipart/form-data">
       
   input框中的name属性必不可少,要不然传递不到后台,并且应该与实体类的字段保持一致才能自动的封装为JavaBean对象 
       后台需要接收前台的数据,直接与前台的name属性值保持一致即可

 // jq里ajax的processData为true时(默认),不能序列化对象,将直接以data的形式传入,为false时,data序列化
 // 成可传输储存的状态,在这里设成false表示将data数据序列化传输,函数视图可以获取数据,如果在默认为true的情况
 // 下,函数视图获取不到数据

三、后端代码


 @Controller
public class TeamController {
    @Autowired
    private TeamImageServiceImpl teamImageService;
    @Autowired
    private ITeamService teamService;
    @Autowired
    private ITeamIntroduceService teamIntroduceService;

    @RequestMapping(value = "/teamRegister")
    @ResponseBody
    public Map<String, Object> register(Team team, @RequestParam("intro") String intro, @RequestParam("file") MultipartFile file) throws IOException {
        Map<String, Object> map = new HashMap<>();

        String teamName = team.getName();//获取前端传递的队伍名称

        String randomNumber = UUID.randomUUID().toString().replace("-", "");//使用UUID生成唯一标识
//创建一个唯一标识作为评论的主键以及队伍的一个字段,方便用来保存数据将队伍与队伍描述建立起关系

        String oldFilename = file.getOriginalFilename(); //获取文件的原始名

        String extension = FilenameUtils.getExtension(file.getOriginalFilename());//使用FilenameUtils获得文件的后缀(先导依赖Commons-fileUpload)

        String newFileName = teamName + randomNumber + "." + extension; //生成新的文件名(队伍名+随机数+后缀名)

        String fileUploadDir = ResourceUtils.getURL("classpath:").getPath() + "/static/teamImages"; //使用ResourceUtils类路径再获取文件保存的路径


        String namespace = fileUploadDir + newFileName; //队标的全路径(从盘符开始)

        String relativePath = "/static/teamImages" + newFileName; //文件保存的相对路径

        team.setUuidNumber(randomNumber);

        team.setImgPath(relativePath);

        File dateDir = new File(fileUploadDir);

        if (!dateDir.exists()) {
            dateDir.mkdirs();//判断目录是否存在,不存在则直接创建
        }
        file.transferTo(new File(fileUploadDir, newFileName));

        TeamImage teamImage = new TeamImage(oldFilename, newFileName, relativePath, extension, new Date());

        teamService.saveTeam(team);//保存team对象

        teamImage.setTeam(team); //teamImage保存team

        teamImageService.saveTeamImage(teamImage); //保存teamImage

        TeamIntroduce introduce = new TeamIntroduce(randomNumber, team.getId(), intro);
        teamIntroduceService.saveTeamIntroduce(introduce);
        
        return map;
    }

}

效果

SpringBoot实现文件的上传以及表单数据的同时提交

MySQL数据库
SpringBoot实现文件的上传以及表单数据的同时提交

MongoDB
SpringBoot实现文件的上传以及表单数据的同时提交

可能出现的错误

报错Required String parameter ‘xxxx’ is not present
基本上就是前端的数据并没有成功的传递过来,而后端又用@RequestParam(value="name")来接收考虑前端name属性与@RequestParam的参数是否一致

如果前端传入的是json数据那么后端使用
@RequestBody HashMap<String, String> map
进行接收,然后再通过map.get(“name”)获取对应的数据

如果前端传入的是正常表单数据,那么后端使用
@RequestParam("name") String name 或者
@RequestParam(value="name", required = false) String name接收参数

需要注意的是,如果请求类型为delete并且参数类型不是json的话,不能使用通过表单类型提交,参数需要跟到请求url后面,并且后台使用@PathVariable进行获取参数

上一篇:关于javascript中限定时间内防止按钮重复点击的思路


下一篇:C# .net aspx 前端获取session