SSM表单异步提交图片(FormData)以及其他内容并且存入数据库记录

SSM表单提交图片(FormData)以及其他内容并且存入数据库记录

最近学习使用到Spring + SpringMVC + MyBatis 整合,并且做一个小小的案例网站.其中向数据库中添加一条新的信息,涉及到了图片上传.新人入手总是大坑小坑不断,为此在这里记录一下自己在这个上传图片并且存储数据库的功能中遇到的问题.

因为在没有使用SSM框架之前,表单提交文件直接使用了多部分提交以及注解,大家一定也了解,所以在SSM的案例中,想当然的使用了之前的方式,结果实现起来总是那么不尽人意,先来贴一下最开始的代码
(以下内容纯属自己学习过程中积累经验,写的不好,希望各位见谅.欢迎大佬们给提一些宝贵意见)

jsp前端代码(样式是页面携带,请省略):

<form action="${pageContext.request.contextPath}/AddServlet" method="post" id="addForm" enctype="multipart/form-data">
        <div class="form-group">
            <label for="rname">线路名:</label>
            <input type="text" class="form-control" id="rname"  name="rname" placeholder="请输入线路名" />
            <span style="color: red" id="sp"></span>
        </div>
        
        <div class="form-group">
            <label for="price">线路价格:</label>
            <input type="text" class="form-control" id="price" name="price" placeholder="请输入线路价格" />
        </div>
        
        <div class="form-group">
            <label for="routeIntroduce">线路描述:</label>
            <input type="text" class="form-control" id="routeIntroduce" name="routeIntroduce"  placeholder="请输入线路描述"/>
        </div>
        
        <div class="form-group">
            <label for="rimage">选择图片:</label>
            <input type="file" class="form-control" id="rimage" name="rimage" onchange="changeImg()" />
        </div>
        
        <div class="form-group" style="text-align: center">
            <input class="btn btn-primary" type="submit" value="提交" id="submitBtn" />
            <input class="btn btn-default" type="reset" value="重置" />
            <input class="btn btn-default" type="button" value="返回"/>
        </div>
    </form>
</div>

java后端代码:

/**
     * 上传文件以及获取提交普通表单项
     * 使用注解 标注MultipartFile对象
     * @RequestParam(value="rimage",required=false)
     * @return
     */
    @RequestMapping("/uploadAndCount")
    public String uploadAndCount(@RequestParam(value="rimages") MultipartFile file,String rname,String price,String routeIntroduce){
        if (file != null){
            try {
                // 获取文件名
                String filename = file.getOriginalFilename();
                // 上传到服务器
                // 指定上传到服务器的路径 并且拼接文件名
                String uploadSrc = "E:\\TomcatImage\\"+filename;
                // 调用方法上传
                file.transferTo(new File(uploadSrc));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("测试名称:"+rname);
        System.out.println("测试价格:"+price);
        System.out.println("测试介绍:"+routeIntroduce);

        return null;
    }

上面的上传方式虽然实现的图片上传到服务器,但是总感觉驴唇不对马嘴.
表单使用了多部分提交,enctype=“multipart/form-data”,服务器部分@RequestParam(value=“rimages”)注解 标注MultipartFile对象,获取到前台提交的图片的文件对象.
但是为了存储其他的数据,再使用方法形参接收参数,因为设置了表单多部分提交,导致无法直接用模型传入参数.这样一来使得本来改简洁的程序更加复杂了.
-----------------------------------------------我是华丽的分割线------------------------------------------------

有幸通过百度以及论坛 找到了另一种方法,通过异步的方式,将图片和其他表单信息分开提交,并且存入数据库.下面介绍一下具体实现
1
jsp前端代码:

<form action="${pageContext.request.contextPath}/uploadAndCount" method="post" id="addForm" >
        <div class="form-group">
            <label for="rname">线路名:</label>
            <input type="text" class="form-control" id="rname"  name="rname" placeholder="请输入线路名" />
            <span style="color: red" id="sp"></span>
        </div>

        <div class="form-group">
            <label for="price">线路价格:</label>
            <input type="text" class="form-control" id="price" name="price" placeholder="请输入线路价格" />
        </div>

        <div class="form-group">
            <label for="routeIntroduce">线路描述:</label>
            <input type="text" class="form-control" id="routeIntroduce" name="routeIntroduce"  placeholder="请输入线路描述"/>
        </div>

        <div class="form-group">
            <label for="rimage">选择图片:</label>
            <input type="file" class="form-control" id="rimage" name="rimage" onchange="changeImg()" />
        </div>

        <div class="form-group" style="text-align: center">
            <input class="btn btn-primary" type="submit" value="提交" id="submitBtn" />
            <input class="btn btn-default" type="reset" value="重置" />
            <input class="btn btn-default" type="button" value="返回"/>
        </div>
    </form>

<script>
$("#rimage").blur(function () {
        console.log("选择图片完毕");
        // 获取表单对象
        var form = document.getElementById("addForm");
        // 根据表单对象创建FormData对象
        var formData = new FormData(form);
        // 获取到表单中选择的图片信息
        var file = this.files[0];
        // 因为我是用的是文件选择框失去焦点的时候去发送请求,所以判断file是否为空,
        // 即如果没有选择文件就不进行ajax的提交
        if (file==null){
            return;
        }
        // 通过append方法向formData中添加数据
        formData.append("rimage",file);
		// 进行ajax的请求设置
        $.ajax({
            url: '${pageContext.request.contextPath}/ajaxUpload', // 提交到后台的controller
            type: 'POST',  // 提交方式
            cache: false,  // 设置不让页面缓存
            data: formData,  // 提交的数据 
            dataType: 'json',  // 提交数据的格式 这里用json
            processData: false,    //不需要对数据做任何预处理
            contentType: false    //不设置数据格式
        });

    });
</script>

这次的前端代码和之前相比,表单不再设置 多部分提交,并且添加了FormData获取图片的信息以及使用jQuery支持的ajax实现异步提交图片到服务器.因为我们没有设置表单的多部分提交,所以在后台进行普通文本项提交获取的时候可以使用模型去自动封装数据.
2
接收ajax的controller

 /**
     * formData的异步提交图片
     * @param file
     * @return
     */
    @RequestMapping("/ajaxUpload")
    public void ajaxUpload(@RequestParam("rimage") MultipartFile file){
        try {
            // 获取到全段上传文件的文件名 并且与我们服务器存放图片的地址进行拼接
            String uploadSrc = "E:\\TomcatImage\\"+file.getOriginalFilename();
            // 将拼接后的路径作为一个File对象 通过transferTo方法进行上传
            file.transferTo(new File(uploadSrc));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

因为ajax只是异步提交的图片信息,所以我直接获取了file对象,进行图片到服务器的上传
(值得一提的是,这里的@RequestParam(“rimage”)参数一定要注意和前端的input控件的name属性保持一致,本人因多次修改代码,导致这里好几次被遗忘,无辜的报错.)
3
将数据存入数据库的controller:

/**
     * 添加信息到数据库
     * @param route
     * @return
     */
    @RequestMapping("/AddServlet")
    public String add(Route route){
        /*
            将图片存入数据库 我们存入数据库的应该是访问的路径
            将服务器的图片访问路径与前台传入的图片名称进行拼接 得到完整的数据库存储路径
         */
        String saveSrc = "http://localhost:8080/Image/"+route.getRimage();
        // 因为我们使用的模型直接封装前台的数据 所以需要将javaBean中的图片路径地址进行一下更新
        route.setRimage(saveSrc);
        // 调用自己的添加方法 将信息插入到我们的数据库中
        routeService.add(route);
        // 重定向到查询的controller 这里衔接其他内容
        return "redirect:findAll";
    }

直接通过模型获取前端返回的普通表单项的数据,然后对存入数据库的图片路径进行一些修改,我是直接将我配置的图片路劲进行拼接(使用的Tomcat服务器,配置虚拟的存放路径,从idea上配置映射路径)
3
顺便说一下 配置文件中的文件上传配置不要遗忘

<!-- 配置文件上传解析器  要求ID必须是multipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设置文件的最大尺寸 -->
        <property name="maxUploadSize" value="#{1024*10240}" />
        <!-- 设置默认的编码格式-->
        <property name="defaultEncoding" value="UTF-8" /> 
    </bean>

4
至此为止,完成了更改后的表单图片上传以及普通信息的提交,做一个小小的总结吧

  1. 上传图片和普通信息分开进行,不要直接给表单设置多部分提交,否则会使我们在后台获取其他信息变得复杂.
  2. 使用ajax异步(同步也可以)进行图片的提交,分步进行
  3. 在controller中获取提交的文件信息是,一定要保证@RequestParam直接的value值也表单控件相对应
  4. SpringMVC配置文件中不要忘记配置文件上传解析器,并且注意ID的值为multipartResolver

5
接触java这些时间,大大小小的问题也是接连不断,但是每次解决bug或者修改不如意的代码之后总是感觉自己又开拓了新大陆一般.作为一个小菜鸟,永远不能停下自己学习的脚步,同时也希望自己以后的能力越来越强.

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页