实战SSM_O2O商铺_15【商铺注册】View层+Controller层之图片上传

概述

关于结合Spring + Spring MVC 实现文件上传下载,之前总结了几篇

Spring MVC-09循序渐进之文件上传(基于Apache Commons FileUpload)

Spring MVC-09循序渐进之文件上传(基于Servlet3.0+内置功能)

Spring MVC-09循序渐进之文件上传(基于Servlet3.0+Html5客户端上传文件)

Spring MVC-10循序渐进之文件下载

这里我们选择使用基于Apache Commons FileUpload的方式


Maven依赖

    <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.2</version>
        </dependency>

文件上传解析器bean的配置

/o2o/src/main/resources/spring/spring-web.xml

    <!-- 文件上传解析器 -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="utf-8"></property>
        <property name="maxUploadSize" value="10485760000"></property><!-- 最大上传文件大小 -->
        <property name="maxInMemorySize" value="10960"></property>
    </bean>

页面

shopoperation.html增加上传组件

/o2o/src/main/webapp/WEB-INF/html/shop/shopoperation.html

type=”file” ,并且设置id,方便js中操作

<!-- 商铺图片  上传组件-->
                        <li class="item-content">
                            <div class="item-inner">
                                <div class="item-inner">
                                    <div class="item-title label">商铺图片</div>
                                    <div class="item-input">
                                        <input type="file" id="shop-img">
                                    </div>
                                </div>
                            </div>
                        </li>

html尾部引入shopoperation.js

    <!-- 加载自定义的JS -->
    <script type='text/javascript'
        src='../resources/js/shop/shopoperation.js' charset='utf-8'></script>

shopoperation.js

/o2o/src/main/webapp/resources/js/shop/shopoperation.js

获取shopImg ,(因为只能上传一张图片,所以$(‘#shop-img’)[0].files[0]) ,添加到formData中,使用ajax提交到后台

/**
     * submit按钮触发的操作
     */
    $('#submit').click(function() {
        // 获取页面的值
        省略....
        省略....

        // 图片
        var shopImg = $('#shop-img')[0].files[0];


        // 接收数据
        var formData = new FormData();
        // 和后端约定好,利用shopImg和 shopStr接收 shop图片信息和shop信息
        formData.append('shopImg',shopImg);

        // 转成JSON格式,后端收到后将JSON转为实体类
        formData.append('shopStr',JSON.stringify(shop));

        // 将数据封装到formData发送到后台
        formData.append('verifyCodeActual',verifyCodeActual);


        // 利用ajax提交
        $.ajax({
            url:registerShopUrl,
            type:'POST',
            data:formData,
            contentType:false,
            processData:false,
            cache:false,
            success:function(data){
                if(data.success){
                    $.toast('提示信息:'+data.errMsg);
                }else{
                    $.toast('提示信息:' + data.errMsg);
                }
                // 点击提交后 不管成功失败都更换验证码,防止重复提交
                $('#kaptcha_img').click();
            }
        });

    });

Controller层

/o2o/src/main/java/com/artisan/o2o/web/shopadmin/ShopController#registerShop方法

控制层的方法接收到前端的请求后,从MultipartHttpServletRequest 中获取到CommonsMultipartFile类型的 shopImg,同时为了简化Controller层调用Service层的难度,这里我们对Service的addShop做了改造,这样就避免了将CommonsMultipartFile转换为File,而是通过CommonsMultipartFile的getInputStream()方法,以流的形式作为入参(因为Thumbnail也可以处理流)。

控制层调用Service层,Service层addShop方法根据入参获取到文件的后缀名后,写入shop的基本信息,然后调用工具类获取文件的存储路径,将图片打上水印存入对应的文件目录,最后更新到tb_shop。具体见 实战SSM_O2O商铺_10【商铺注册】Service层的实现

@RequestMapping(value = "/registshop", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> registerShop(HttpServletRequest request) {
        Map<String, Object> modelMap = new HashMap<String, Object>();
        // 0. 验证码校验
            省略......
        // 1. 接收并转换相应的参数,包括shop信息和图片信息

            省略......

        // 1.2 图片信息 基于Apache Commons FileUpload的文件上传

        // Spring MVC中的 图片存在CommonsMultipartFile中
        CommonsMultipartFile shopImg = null;
        // 从request的本次会话中的上线文中获取图片的相关内容
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
        if (commonsMultipartResolver.isMultipart(request)) {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            // shopImg是和前端约定好的变量名
            shopImg = (CommonsMultipartFile) multipartRequest.getFile("shopImg");
        } else {
            // 将错误信息返回给前台
            modelMap.put("success", false);
            modelMap.put("errMsg", "图片信息为空");
            return modelMap;
        }

        // 2. 注册店铺
        if (shop != null && shopImg != null) {
            // Session TODO
            // 店主persionInfo的信息,肯定要登录才能注册店铺。
            // 所以这部分信息我们从session中获取,尽量不依赖前端,这里暂时时不具备条件,后续改造,先硬编码,方便单元测试
            PersonInfo personInfo = new PersonInfo();
            personInfo.setUserId(1L);

            shop.setOwner(personInfo);
            // 注册店铺

            // se = shopService.addShop(shop, shopImg); 改造前的调用方式
            // 这个时候,我们从前端获取到的shopImg是CommonsMultipartFile类型的,如何将CommonsMultipartFile转换为file.
            // 网上也有将CommonsMultipartFile转换为File的方法,并通过maxInMemorySize的设置尽量不产生临时文件
            // 这里我们换个思路,因为CommonsMultipartFile可以获取InputStream,Thumbnailator又可以直接处理输入流
            // 因为InputStream中我们无法得到文件的名称,而thumbnail中需要根据文件名来获取扩展名,所以还要再加一个参数String类型的fileName
            // 既然第二个和第三个参数都是通过shopImg获取的,为什么不直接传入一个shopImg呢?
            // 主要是为了service层单元测测试的方便,因为service层很难实例化出一个CommonsMultipartFile类型的实例
            ShopExecution se = null;;
            try {
                se = shopService.addShop(shop, shopImg.getInputStream(), shopImg.getOriginalFilename());
                if (se.getState() == ShopStateEnum.CHECK.getState()) {
                    modelMap.put("success", true);
                    modelMap.put("errMsg", "注册成功");
                } else {
                    modelMap.put("success", false);
                    modelMap.put("errMsg", se.getStateInfo());
                }
            } catch (IOException e) {
                e.printStackTrace();
                modelMap.put("success", false);
                modelMap.put("errMsg", "addShop Error");
            }
        } else {
            // 将错误信息返回给前台
            modelMap.put("success", false);
            modelMap.put("errMsg", "请输入店铺信息");
        }
        return modelMap;
    }

处理成功后,返回前台JSON数据,给用户提示

猜你喜欢

转载自blog.csdn.net/yangshangwei/article/details/80504322
今日推荐