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

文章目录

  • 概述
  • Maven依赖
  • 文件上传解析器bean的配置
  • 页面
    • shopoperation.html增加上传组件
    • shopoperation.js
  • Controller层
  • Github地址

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

概述

关于结合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数据,给用户提示


Github地址

代码地址: https://github.com/yangshangwei/o2o

你可能感兴趣的:(【实战-SSM,In,Action】,实战系列-SSM实战)