如何用Ajax发带有文件的表单请求到接口

本文介绍的方法在上传文件时先上传到本地,在发请求时一并传到接口再进行后续处理。

1、ftl页面

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>个人店铺设置</title>
    <link rel="stylesheet" href="xxx/css/shop-setting.css">
    <script src="xxx/js/lib/require.js"></script>
</head>

<body>
<div>
    <form id="setting-form" method="POST" enctype="multipart/form-data" role="form">
        <div>
            店铺名称:
            <input type="text" id="shopName" name="shopName">
        </div>
        <div>
            我的手机:
            <input type="text" id="userMobile" name="userMobile">
        </div>
        <div>
            我的头像:
            <img src="xxx" id="headPicture" alt="头像图片">
            <input type="file" id="chooseHeadPicture">
        </div>
        <div>
            微信二维码:
            <img src="xxx" id="wechatPicture" alt="微信二维码图片">
            <input type="file" id="chooseWechatPicture">
        </div>
        <div>
            <button type="button" id="submit">提交</button>
        </div>
    </form>
</div>

<script src="xxx/js/personalShop/edit.js"></script>
</body>

</html>

这里注意在form中使用enctype ="multipart/form-data",来使请求头的contentType=multipart/form-data

2、edit.js

...
$(function(){
        var edit = {
            init : function(){
                this.checkInput();
                this.submitEdit();
            },
            checkInput:function(){
                $("#setting-form").validate({
                    rules:{
                        shopName:{
                            required:true,
                            maxlength:30,
                        },
                        userMobile:{
                            required:true,
                            maxlength:30,
                        },
                    },
                    messages:{
                        shopName:{
                            required:"必填项",
                            maxlength:"最多输入30个字符",
                        },
                        userMobile:{
                            required:"必填项",
                            maxlength:"最多输入30个字符",
                        },
                    }
                });

                $("#chooseHeadPicture").on("change",function () {
                    var path = $(this).val();
                    var imgType = path.substring(path.lastIndexOf(".")).toLowerCase();
                    var headPicSrc = window.URL.createObjectURL(this.files[0]);
                    var imgSize = this.files[0].size;
                    var id = $("#headPicture");
                    edit.checkPicture(imgType,imgSize,headPicSrc,id);
                });

                $("#chooseWechatPicture").on("change",function(){
                    var path = $(this).val();
                    var imgType = path.substring(path.lastIndexOf(".")).toLowerCase();
                    var headPicSrc = window.URL.createObjectURL(this.files[0]);
                    var imgSize = this.files[0].size;
                    var id = $("#wechatPicture");
                    edit.checkPicture(imgType,imgSize,headPicSrc,id);
                });

            },

            //检查图片格式及大小
            checkPicture :function(imgType,imgSize,src,id){
                if (!imgType.match(/.jpg|.jpeg|.gif|.png|.bmp/)) {
                    //alert("图片格式必须为jpg,jpeg,gif,png或bmp");
                    return;
                } else if(imgSize/1024/1024 > 1){
                    //alert("图片不允许大于1M");
                    return;
                }else {
                    //当图片符合要求,使其在页面上展示
                    id.attr("src", src);
                }
            },

            submitEdit:function () {
                $("#submit").click(function () {
                    var formData = new FormData();
                    formData.append("shopName",$.trim($("#shopName").val()));
                    formData.append("userMobile",$.trim($("#userMobile").val()));

                    if($("#chooseHeadPicture").val()){
                        formData.append("headPicture",$("#chooseHeadPicture")[0].files[0]);
                    }
                    if($("#chooseWechatPicture").val()){
                        formData.append("wechatPicture",$("#chooseWechatPicture")[0].files[0]);
                    }

                    $.ajax({
                        url:'xxx/personalShop/editPersonalShopInfo',
                        //jQuery参数,默认为false,当设置为true的时候,ajax提交的时候不会序列化data,而是直接使用data
                        processData: false,
                        //避免jQuery对contentType进行操作,从而与<form>中的enctype="multipart/form-data产生冲突
                        contentType: false,
                        //上传文件不需要缓存
                        cache: false,
                        type:"POST",
                        data:formData,
                        success:function (data) {
                            
                        }
                    })
                });
            }

        };
        edit.init();
    })

这里使用FormData对象处理文本、文件等数据然后发Ajax请求,Ajax发送的数据也是formData。

FormData也类似json键值对的形式,关于FormData更多介绍可参考:FormData对象的使用

关于contentType的介绍可以参考:Ajax 请求头中常见content-type

3、controller层

PresonalShopController.java
...
@Controller
@RequestMapping(value="/xxx/personalShop")
public class PersonalShopController {
    @RequestMapping("/edit")
    public Response edit(EditPersonalShoptRequest request){
        ...
    }
}
EditPersonalShopRequest.java
...
public class EditPersonalShoptRequest {
    /**
     * 店铺名称
     */
    private String shopName;

    /**
     * 我的手机
     */
    private String userMobile;

    /**
     * 头像
     */
    private MultipartFile headPicture;

    /**
     * 我的微信
     */
    private MultipartFile wechatPicture;

    ...set/get
}

接口的入参还是写的一个对象,只要把文件类型用MultipartFile定义,当Ajax请求时,同样会把js文件中定义的formData和controller的入参关联映射。这样做的好处就是当把入参封装成一个对象,当需要传的值很多时controller看起来也比较简洁。

注意:

  1. formData.append("shopName",$.trim($("#shopName").val()));中"shopName"要与controller入参中private String shopName一致,否则无法正常映射;
  2. controller入参前不需要@RequestBody来注解,因为http请求中contentType=multipart/form-data而不是application/json;

当然controller入参也可以分开来写:

PresonalShopController.java
...
@Controller
@RequestMapping(value="/xxx/personalShop")
public class PersonalShopController {
    @RequestMapping("/edit")
    public Response edit(@RequestParam(name = "shopName") String shopName,
                         @RequestParam(name = "userMobile") String userMobile,
                         @RequestParam(name = "headPicture", required = false) MultipartFile headPicture,
                         @RequestParam(name = "weChatPicture", required = false) MultipartFile weChatPicture){
        ...
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值