当前位置:   article > 正文

SpringBoot+MyBatis+MYSQL项目实战五(用户上传头像,上传文件,两种ajax提交方式FormData和serialize)

SpringBoot+MyBatis+MYSQL项目实战五(用户上传头像,上传文件,两种ajax提交方式FormData和serialize)

SpringBoot+MyBatis+MYSQL项目实战五(上传头像)

项目源码地址:电脑商城实战

一:上传头像——持久层

1.1SQL语句的规划

update t_user set avatar=?,modified_user=?,modified_time=? where uid=?
  • 1

1.2设计接口和抽象方法
UserMapper接口定义方法

/**
     * @Param("SQL映射文件中的#{} 占位符的变量名"):解决的问题:当SQL语句的占位符和映射的接口方法参数名不一致是,
     * 需要将某个参数强行注入到某个占位符变量上是,使用这个@param这个注解来标注映射关系。
     * 根据用户uid值来修改用户的头像
     * @param uid
     * @param avatar
     * @param modifiedUser
     * @param modifiedTime
     * @return
     */
    Integer updateAvatarByUid(
            @Param("uid") Integer uid,
            @Param("avatar") String avatar,
            @Param("modifiedUser") String modifiedUser,
            @Param("modifiedTime") String modifiedTime);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

1.3接口映射

<update id="updateAvatarByUid">
        UPDATE  t_user
        SET
           avatar = #{avatar},
           modified_user = #{modifiedUser},
           modified_time = #{modifiedTime}
        WHERE
           uid = #{uid}
    </update>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

1.4测试

@Test
    public void updateAvatarByUid(){
        Integer rows = userMapper.updateAvatarByUid(10, "123", "管理者", new Date());
        System.out.println(rows);
    }
  • 1
  • 2
  • 3
  • 4
  • 5

二:上传头像——业务层

2.1规划异常

在修改头像值前先检查用户数据状态,可能抛UserNotFoundException异常;由于最终执行的是修改操作还可能抛UpdateException异常。
2.2设计接口和抽象方法

    /**
     * 修改用户的头像
     * @param uid 用户的id
     * @param avatar 用户的图片
     * @param modifiedUser 修改者
     */
    void updateAvatarByUid(Integer uid,String avatar,String modifiedUser);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
@Override
    public void updateAvatarByUid(Integer uid, String avatar, String modifiedUser) {
        User result = userMapper.findByUid(uid);
        if (result ==null || result.getIsDelete().equals(1)){
            throw new UserNotFoundException("用户数据不存在");
        }
        Integer rows = userMapper.updateAvatarByUid(uid, avatar, modifiedUser, new Date());
        if (rows != 1){
            throw new UpdateException("更新用户头像产生未知的异常");
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2.3编写测试类

@Test
    public void updateAvatarByUid(){
        UserService.updateAvatarByUid(10,"/static/images/","管理者");
    }
  • 1
  • 2
  • 3
  • 4

三:上传头像——控制层

3.1规划异常

FileUploadException 泛指文件上传的异常(父类) 继承RuntimeException

父类是FileUploadException
FileEmptyException 文件为空的异常
FileSizeException 文件大小超出限制
FileTypeException 文件类型异常
FileUploadException 文件读写的异常
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

五个构造方法声明出来,再去继承。
3.2 处理异常
在基类BaseController中统一处理

else if(e instanceof FileEmptyException){
            result.setState(6000);
            
        }
        else if(e instanceof FileSizeException){
            result.setState(6001);
           
        }
        else if(e instanceof FileTypeException){
            result.setState(6002);
            
        }
        else if(e instanceof FileStateException){
            result.setState(6003);
            
        }
        else if(e instanceof FileUploadException){
            result.setState(6004);
            
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在异常统一处理方法的参数列表上增加新的异常处理作为他的参数

@ExceptionHandler({ServiceException.class,FileUploadException.class})
  • 1

3.3设计请求
设计用户提交的请求,并设计响应的方式:

请求路径:/users/change_avatar
请求参数:MultipartFile file, HttpSession session
请求类型:POST
响应结果:JsonResult<String>
  • 1
  • 2
  • 3
  • 4

3.4实现请求


    /**
     * MultipartFile 接口是SPingMvc接口,这个接口为我们包装了获取文件类型的数据(任何类型的file都可以接收)
     * springboot它整合了springmvc,只需要在处理请求的方法参数列表上声明一个参数类型MultipartFile的
     * 参数,然后springboot会自动传递给服务的文件数据复制给这个参数
     *
     * @RequestParam 表示请求中的参数,将请求中的参数注入请求处理方法的某个参数上,如果名称不一致则可以使用
     * @RequestParam如果名称不一致则可以使用@RequestParam
     * @param session
     * @param file
     * @return
     */
    @RequestMapping(value = "/change_avatar",method = RequestMethod.POST)
    public JsonResult<String> upload(HttpSession session,
                                     @RequestParam("file") MultipartFile file){

        return new JsonResult<>(OK);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
@RequestMapping(value = "/change_avatar",method = RequestMethod.POST)
    public JsonResult<String> upload(HttpSession session,
                                     @RequestParam("file") MultipartFile file) throws IOException {
        // 判断文件是否为空
        if(file.isEmpty()){
            throw new FileEmptyException("文件为空");
        }
        if(file.getSize() > AVATAR_MAX_SIZE){
            throw new FileSizeException("文件超出限制");
        }
        String contentType = file.getContentType();
        // 如果集合包含某个元素则返回值true
        if (AVATAR_TYPE.contains(contentType)){
            throw new FileTypeException("文件类型不支持");
        }
        //上传的文件../upload/
        String parent = session.getServletContext().getRealPath("upload");

        // File 对象指向这个路劲,File是否存在
        File dir = new File(parent);
        if(!dir.exists()){
            dir.mkdirs(); //创建文件夹
        }
        // 获取到这个文件名称,UUID工具生成一个新的字符串作为文件名
        String originalFilename = file.getOriginalFilename();
        System.out.println("OriginalFilename"+originalFilename);
        int index = originalFilename.lastIndexOf(".");
        String suffix = originalFilename.substring(index);
        String filename = UUID.randomUUID().toString().toUpperCase() + suffix;
        File dest = new File(dir,filename);  //空文件
        // 参数file中的数据写入到这个空文件中
        try {
            file.transferTo(dest); //将file文件中的数据写入dest文件中
        }catch (FileStateException e){
            throw new FileStateException("文件状态异常");
        }
        catch (IOException e) {
            throw new FileUploadIOException("文件读写异常");
        }
        Integer uid = getuidFromSession(session);
        String username = getUsernameFromSession(session);
        // 返回头像的路径
        String avatar = "/upload/" + filename;
        iUserService.updateAvatarByUid(uid,avatar,username);
        // 返回用户头像路径给其阿奴但,将来用户头像头像展示使用
        return new JsonResult<>(OK,avatar);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

四:上传头像——前端页面

注意;action="/users/change_avatar" method="post" enctype="multipart/form-data"

<form class="form-horizontal" action="/users/change_avatar"
							  method="post" enctype="multipart/form-data" role="form">
							<div class="form-group">
								<label class="col-md-2 control-label">选择头像:</label>
								<div class="col-md-5">
									<img id="img-avatar" src="../../static/images/index/user.jpg" class="img-responsive" />
								</div>
								<div class="clearfix"></div>
								<div class="col-md-offset-2 col-md-4">
									<input type="file" name="file">
								</div>
							</div>
							<div class="form-group">
								<div class="col-sm-offset-2 col-sm-10">
									<input type="submit" class="btn btn-primary" value="上传" />
								</div>
							</div>
						</form>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

五解决Bug

5.1更改默认的大小限制
SpringMVC默认为1MB文件可以进行上传,手动的去修改SpringMvC默认上传文件的大小
方式一:直接在配置文件中配置

  spring
  servlet:
    multipart:
      max-file-size: 15MB
      max-request-size: 20MB
  • 1
  • 2
  • 3
  • 4
  • 5

方式二:采用java代码的形式设置文件的上传大小的限制,主类中进行配置,可以定义一个方法,必须使用@bean修饰,在类的前面添加@Configration注解进行修改

  @Bean
    public MultipartConfigElement getMultipartConfigElement(){
        //创建一个配置的工厂类对象
        MultipartConfigFactory factory = new MultipartConfigFactory();

        factory.setMaxFileSize(DataSize.of(10, DataUnit.MEGABYTES));
        factory.setMaxRequestSize(DataSize.of(15,DataUnit.MEGABYTES));
        return factory.createMultipartConfig();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • serialize():可以将表单数据自动拼接成key=value的结构进行提交给服务器,已办提交是普通的空间类型的数据(text/password\radio\checkboc)
  • FormData类:将表单数据保持原有的结构进行数据的提交。new FormData($("#form")[0]);//为文件类型的数据可以是同FormData对象进行存储
  • ajax默认处理数据是按照字符串的形式进行处理,以及采用默认字符串的形式进行提交。关闭这两个默认的功能。
  • processData: false, //关闭处理数据 contentType: false, //提交数据的形式

5.2登录后显示头像
可以更新头像成功后,将服务器的头像返回路径保存在客户端cookie对象,然后每次检测到用户打开头像页面,在这个页面通过ready()方法来自动检测去读取cookie中头像并设到src属性上。
1.设置cookie中的值
导入cookie的js文件

$.cookie(key,value,time); //单位为天
  • 1

在登录的时候// 将头像保存在cookie中
$.cookie("avatar",json.data.avatar, {expires: 7});

在上传图片的页面使用$(document).ready(function () {}

$(document).ready(function () {
			let avatar = $.cookie("avatar");
			$("#img-avatar").attr("src",avatar);
		})
  • 1
  • 2
  • 3
  • 4

最后在用户上传图片之后更新cookie的值

$("#btn-change-avatar").click(function () {
			$.ajax({
				url: "/users/change_avatar",
				type: "POST",
				data : new FormData($("#form-change-avatar")[0]),
				processData: false, //关闭处理数据
				contentType: false, //提交数据的形式
				dataType: "JSON",
				success: function (json) {
					if(json.state == 200){
						alert("头像修改成功")
						// attr(s属性,属性值):给某个属性设置某个值
						$("#img-avatar").attr("src",json.data);
						$.cookie("avatar",json.data,
								{expires: 7});
						location.href = "/upload";


					}
					else{
						alert("头像修改失败")
					}
				},
				error: function (xhr) {
					alert("修改头像时产生位置的异常"+xhr.message);
				}
			})
		})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/393376
推荐阅读
相关标签
  

闽ICP备14008679号