用户上传头像以及BUG修改

持久层

1、sql语句的规划

上传文件的操作其实是:先将用户上传的文件保存到服务器端的某个位置,然后将保存文件的路径记录在数据库中。当后续需要使用该文件时,从数据库中读出文件的路径,即可实现在线访问该文件。
在持久层处理数据库中的数据时,只需要关心如何记录头像文件的路径,并不需要考虑上传时保存文件的过程。所以,需要执行的SQL语句大致是:

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

2、设计接口与抽象方法

在UserMapper接口中添加updateAvatarByUid()抽象方法。

/*** 根据用户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") Date modifiedTime);

3、接口的映射

<update id="updateAvatarByUid">update store.t_user set avatar=#{avatar}, modified_user=#{modified_user}, modified_time=#{modified_time} where uid=#{uid}</update>

3、测试

 @Testpublic void updateAvatarByUid() {Integer uid = 8;String avatar = "/upload/avatar.png";String modifiedUser = "超级管理员";Date modifiedTime = new Date();Integer rows = usermapper.updateAvatarByUid(uid, avatar, modifiedUser, modifiedTime);System.out.println("rows=" + rows);}

业务层

1、规划异常

1、在修改头像值前先检查用户数据状态,可能抛UserNotFoundException异常;

2、由于最终执行的是修改操作还可能抛UpdateException异常。

2、 接口与抽象方法

在IUserService中添加changeAvatar(Integer uid, String username, String avatar)抽象方法。

/*** 修改用户的头像* @param uid        用户uid* @param username     用户头像* @param avatar          用户名称*/void changeAvatar(Integer uid, String username, String avatar);

3、实现抽象方法

1.在UserServiceImpl类中实现changeAvatar(Integer uid, String username, String avatar)方法。

@Overridepublic void changeAvatar(Integer uid, String username, String avatar) {//查询当前用户数据是否存在User result=usermapper.findByUid(uid);if (result==null || result.getIsDelete()==1){throw new UserNotFoundException("用户没有找到");}Integer rows  =  usermapper.updateAvatarByUid(uid, avatar, username, new Date());if (rows != 1) {throw new UpdateException("更新用户头像时出现未知错误");}}

4、在UserServiceTests类中进行单元测试。

@Testpublic void changeavatar(){userService.changeAvatar(8, "小明", "/upload/test.png");}

控制层

1、处理异常

1.在处理上传文件的过程中,用户可能会选择错误的文件上传,此时就应该抛出对应的异常并进行处理。所以需要创建文件上传相关异常的基类,
即在com.cy.store.controller.ex包下创建FileUploadException类,并继承自RuntimeException类。
2.在处理上传的文件过程中,经分析可能会产生以下异常。这些异常类都需要继承自FileUploadException类。

// 上传的文件为空
cn.tedu.store.controller.ex.FileEmptyException
// 上传的文件大小超出了限制值
cn.tedu.store.controller.ex.FileSizeException
// 上传的文件类型超出了限制
cn.tedu.store.controller.ex.FileTypeException
// 上传的文件状态异常
cn.tedu.store.controller.ex.FileStateException
// 上传文件时读写异常
cn.tedu.store.controller.ex.FileUploadIOException

2、处理异常

在BaseController的handleException()的@ExceptionHandler注解中添加FileUploadException.class异常的处理;最后在方法中处理这些异常。

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 FileUploadIOException) {result.setState(6004);}

在这里插入图片描述

3、设计请求

请求路径:/users/change_avatar
请求参数:MultipartFile file, HttpSession session
请求类型:POST
响应结果:JsonResult

4、处理请求

在UserController类中添加处理请求的changeAvatar(@RequestParam(“file”) MultipartFile file, HttpSession session)方法。

 /** 头像文件大小的上限值(10MB) */public static final int AVATAR_MAX_SIZE = 10 * 1024 * 1024;/** 允许上传的头像的文件类型 */public static final List<String> AVATAR_TYPES = new ArrayList<String>();/** 初始化允许上传的头像的文件类型 */static {AVATAR_TYPES.add("image/jpeg");AVATAR_TYPES.add("image/png");AVATAR_TYPES.add("image/bmp");AVATAR_TYPES.add("image/gif");}@RequestMapping("change_avatar")/*** MultipartFile是springmvc的接口,这个接口为我们包装了获取文件类型的数据(任何类型的file文件),* springboot整合了mvc,所以只需要在处理请求的方法参数列表上声明一个参数类型为MultipartFile的参数* 然后springboot自动将传递给服务器的文件数据赋值给这个参数** @RequestParam:表示请求的参数,将请求的参数注入请求处理方法的某个参数上,* 如果名称不一致则可以使用 @RequestParam注解进行标记和映射*/public JsonResult<String> changeAvatar(HttpSession session,@RequestParam("file") MultipartFile file){
// 判断上传的文件是否为空if (file.isEmpty()) {throw new FileEmptyException("上传的头像文件不允许为空");}// 判断上传的文件大小是否超出限制值if (file.getSize() > AVATAR_MAX_SIZE) { // getSize():返回文件的大小,以字节为单位throw new FileSizeException("不允许上传超过" + (AVATAR_MAX_SIZE / 1024) + "KB的头像文件");}// 判断上传的文件类型是否是我们规定的后缀类型String contentType = file.getContentType();// public boolean list.contains(Object o):当前列表若包含某元素,返回结果为true;若不包含该元素,返回结果为false。if (!AVATAR_TYPES.contains(contentType)) {throw new FileTypeException("不支持使用该类型的文件作为头像,允许的文件类型:\n" + AVATAR_TYPES);}// 获取当前项目的绝对磁盘路径String parent = session.getServletContext().getRealPath("upload");// 保存头像文件的文件夹File dir = new File(parent);if (!dir.exists()) {dir.mkdirs();//创建当前目录}// 获取到这个文件的文件名,UUID来生成一个新的字符串String suffix = "";String originalFilename = file.getOriginalFilename();int beginIndex = originalFilename.lastIndexOf(".");if (beginIndex > 0) {suffix = originalFilename.substring(beginIndex);}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("上传文件时读写错误,请稍后重尝试");}// 头像路径String avatar = "/upload/" + filename;// 从Session中获取uid和usernameInteger uid = getuidFromSession(session);String username = getUsernameFromSession(session);// 将头像写入到数据库中userService.changeAvatar(uid, username, avatar);// 返回成功头像路径return new JsonResult<String>(ok, avatar);}

前端页面

在upload.html页面中配置用户上传头像的form表单。
如果直接使用表单进行文件的上传,,需要给表单显示的添加一个属性enctype=“multipart/form-data”,不会将目标文件的数据结构做修改在上传,不同字符串

<form action="/users/change_avatar" method="post"enctype="multipart/form-data"class="form-horizontal" role="form">

完成后启动项目,打开浏览器先登录,再访问http://localhost:8080/web/upload.html进行测试。

部分优化修改

在选择图片时报错:1M
在这里插入图片描述
原因:SpringBoot中默认MultipartResolver的最大文件大小值为1M。如果上传的文件的大小超过1M,会抛FileSizeLimitExceededException异常。

解决:手动修改默认MultipartResolver的最大文件大小,

  1. 直接在配置文件中进行配置
spring.http.multipart.max-file-size=10MB
spring.http.multipart.max-request-size=15MB
  1. 采用java代码的形式来设置的上传大小的限制
    直接在启动类中添加getMultipartConfigElement()方法,并且在启动类之前添加@Configuration注解。
  @Beanpublic MultipartConfigElement getMultipartConfigElement() {MultipartConfigFactory factory = new MultipartConfigFactory();//配置的工厂类对象// 设置文件最大10M,DataUnit提供5中类型B,KB,MB,GB,TBfactory.setMaxFileSize(DataSize.of(10, DataUnit.MEGABYTES));// 设置总上传数据总大小10Mfactory.setMaxRequestSize(DataSize.of(10, DataUnit.MEGABYTES));//通过工厂类来创建MultipartConfigElement对象return factory.createMultipartConfig();}

用户-上传头像-前端页面BUG解决

1、 上传后显示头像

  1. 头像上传成功后,显示上传的头像。在upload.html页面中,是使用img标签来显示头像图片的。首先确定img标签是否添加有id="img-avatar"属性,便于后续访问该标签;而img标签是通过src属性来决定显示哪张图片的,所以修改src该属性的值即可设置需要显示的图片。修改表单添加id="form-change-avatar"属性。修改input标签,添加id="btn-change-avatar"和type="button"属性。
  • serialixe():可以将表单数据自动拼接成key=value的结构进行提交给服务器,一把你叫是普通控件类型中的数据(text/password/radio/checkbox)等等
  • FormData类:将表单数据保持原有的结构进行数据的条件。
    文件类型的数据可以使用formData对象进行存储
new FormData($("#form-change-avatar")[0]

ajax默认处理数据时按照字符串的形式进行处理,以及默认会采用字符串的形式进行提交数据。关闭这两个默认的功能

  • processData:处理数据。默认情况下,processData的值是true,其代表以对象的形式上传的数据都会被转换为字符串的形式上传。而当上传文件的时候,则不需要把其转换为字符串,因此要改成false。
  • contentType:发送数据的格式。其代表的是前端发送数据的格式,默认值application/x-www-form-urlencoded。代表的是ajax的 data是以字符串的形式传递,使用这种传数据的格式,无法传输复杂的数据,比如多维数组、文件等。把contentType设置为false就会改掉之前默认的数据格式,在上传文件时就不会报错。
<script type="text/javascript">$("#btn-change-avatar").click(function() {$.ajax({url: "/users/change_avatar",type: "POST",data: new FormData($("#form-change-avatar")[0]),dataType: "JSON",processData: false, // processData处理数据contentType: false, // contentType发送数据的格式success: function(json) {if (json.state == 200) {alert("修改成功!");//attr(属性,属性值):给某个属性设置某个值$("#img-avatar").attr("src", json.data);} else {alert("修改失败!" + json.message);}},error: function(xhr) {alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + xhr.status);location.href = "login.html";}});});</script>

2、登录后显示头像

1.用户名、用户Id、用户头像等数据,属于常用数据,在客户端的许多页面都可能需要使用,如果每次都向服务器提交请求获取这些数据,是非常不合适的。可以在用户登录成功后,将这些数据存储在客户端本地,后续在客户端中需要显示这些数据时,直接从本地获取即可,无需再向服务器请求这些数据。在客户端本地存取数据时,可以使用Cookie技术。
2.设计思路:当用户登录成功后,将服务器返回的头像路径存储到本地的Cookie中,在打开“上传头像”页面时,从本地的Cookie中读取头像路径并显示即可。在登录login.html页面中,当登录成功后,将用户头像路径保存到Cookie中。

设置cookie的值:
  • 导入cookie.js文件
<script src="../bootstrap3/js/jquery.cookie.js" type="text/javascript" charset="utf-8"></script>
  • 调用cookie方法
$.cookie(key, value, time);//单位:天

在upload.html页面通过ready()自动读取cookie中的数据

$(document).ready(function () {let avatar=	$.cookie("avatar")$("#img-avatar").attr("src", avatar);});
添加头文件

在upload.html页面中,默认并没有引用jqueyr.cookie.js文件,因此无法识别$.cookie()函数;所以需要在upload.html页面head标签内添加jqueyr.cookie.js文件。

<script src="../bootstrap3/js/jquery.cookie.js" type="text/javascript" charset="utf-8"></script>
显示最新头像

以上代码表示“每次打开页面时,读取Cookie中的头像并显示”,如果此时重新上传用户头像,而Cookie中所保存的头像还是之前上传的头像路径值,无法显示最新的用户头像。所以当用户重新上传头像后,还应把新头像的路径更新到Cookie中。

在upload.html页面中,用户头像修改成功后,并将新的用户头像路径保存到Cookie中。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/20639.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML点击头像修改页面,头像修改页.html

&#xfeff;头像修改页 $axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; }; $axure.utils.getOtherPath function() { return resources/Other.html; }; $axure.utils.getReloadPath function() { return resources/reload.htm…

移动端--修改头像

image/*表示选择所有图片格式 使用第三方插件实现头像裁剪 Cropper.jsCropper.js const cropper new Cropper(image, { viewMode: 1, dragMode: move, aspectRatio: 1, autoCropArea: 1, cropBoxMovable: false, cropBoxResizable: false, background: false, movable: true…

奥特曼格斗进化3全人物存档

奥特曼格斗进化3是奥特曼格斗进化系列的第三部作品&#xff0c;随着游戏的一路走来&#xff0c;游戏的可选角色越来越丰富&#xff0c;画面、技能效果、音效等方面也有了长足的进步&#xff0c;但由于角色解锁起来比较复杂&#xff0c;因此小编为大家带来了奥特曼格斗进化3全人…

python:bs4爬取奥特曼,是不是所有奥特曼都长一样

利用pythonbs4爬取奥特曼粉丝联盟的奥特曼图片&#xff0c;难点把其实也没有&#xff0c;就是爬虫不经常搞&#xff0c;容易忘记一些东西。废话不多说&#xff0c;直接上代码 主要引包 import os from pathlib import Path from bs4 import BeautifulSoup from requests impo…

【业界思考】Sam Altman 山姆奥特曼:Idea Generation 创意产生——优秀的创始人对任何事情都有很多想法

Sam Altman 山姆奥特曼:Idea Generation 创意产生——优秀的创始人对任何事情都有很多想法 文章目录 Sam Altman 山姆奥特曼:Idea Generation 创意产生——优秀的创始人对任何事情都有很多想法优秀的创始人对任何事情都有很多想法How do you do that? 你是怎样做的?最好的想…

圆谷英二——特摄电影的开创者

圆谷英二——特摄电影的开创者 圆谷英二人物记录_2019_06_09在成为摄影师之前特摄生涯的开始--《哥斯拉》奥特曼系列《奥特Q的老爹》后记 圆谷英二人物记录_2019_06_09 日本“特摄之神”圆谷英二的生平概述&#xff0c;转述资料片的内容&#xff0c;记录后世人眼中这位工匠的人…

爆火情侣竟不是真人!新版Midjourney效果炸裂,网友:太可怕了

金磊 鱼羊 Pine 发自 凹非寺量子位 | 公众号 QbitAI 注意看&#xff0c;这张情侣照在网上转疯了&#xff1a; 旧厂街风格&#xff0c;带着浓浓90年代氛围感&#xff0c;但是&#xff0c;他俩一夜爆火的原因&#xff0c;你可能想象不到—— 这二位并不是真人&#xff01;而是由A…

随机种子 3407 is all you need

文 | 天于刀刀 你最常用的随机种子是哪个&#xff1f; 在刀刀的团队里&#xff0c;关于随机种子的设置主要分化为两派~ 玄学派&#xff0c;可能设置为自己的纪念日&#xff0c;又或者是星座预测中的本月幸运数字&#xff1b; 以及&#xff0c;自然派&#xff0c;随机种子是啥其…

入门AI到入职,微软首席算法工程师有话要说!

原文来自&#xff1a;异步图书 一边呼吁停止GPT-5研发&#xff0c;一边大肆买入几千台GPU、招募AI牛人成立X.AI搞大模型&#xff0c;马斯克要和OpenAI正面对抗了&#xff01; 在ChatGPT发布之前&#xff0c;马斯克就曾表示OpenAI已经背离了其初衷&#xff0c;背弃了开源理念。G…

腾讯T9级.NET Core招聘又来了,月薪30k+

朝夕Net社区 2022-09-05 18:30 今年腾讯阿里裁员消息屡见不鲜&#xff0c;边裁边招才是真相&#xff0c;随着金九银十到来&#xff0c;腾讯T9级.NET Core招聘又来了&#xff0c;月薪30k&#xff0c;依然香&#xff01;这里推荐个.NET跳槽交流群&#xff0c;有技术交流&#xff…

月薪10.8K,从销售客服转行软件测试斩获4份offer,所有的惊艳都来自长久的准备

时间不会辜负努力的人&#xff0c;不要质疑你的付出&#xff0c;每一次的努力都是在为自己铺路&#xff0c;所有看起来的幸运&#xff0c;都来自于内心的坚定。今天跟大家分享的是我的转行经历&#xff0c;希望所有人今天的努力&#xff0c;在未来都可以收获一个更好的自己。 斟…

这个高薪行业正在大量招人,你会考虑吗?

作者 | 侯淼淼 出品 | 《新程序员》 当人们提及“程序员”这一职业的时候&#xff0c;大多数人的第一想法往往是高薪。然而近年来&#xff0c;随着造车势力的兴起&#xff0c;新一轮的高薪岗位抢人大战正式打响。2021年以来&#xff0c;一汽、东风等传统车厂招聘岗位数量…

月薪10.8K|销售客服转行软件测试斩获4份offer,所有的惊艳都来自长久的准备

时间不会辜负努力的人&#xff0c;不要质疑你的付出&#xff0c;每一次的努力都是在为自己铺路&#xff0c;所有看起来的幸运&#xff0c;都来自于内心的坚定。今天跟大家分享的是近期就业的韩同学的转行经历&#xff0c;希望所有人今天的努力&#xff0c;在未来都可以收获一个…

杭州一公司开出20万月薪/320万年薪抢人!ChatGPT掀起AI热潮,AIGC人才被爆抢

5年工作经历&#xff0c;博士学位&#xff0c;最高月薪20万。 最近&#xff0c;位于杭州未来科技城一家公司&#xff0c;开出了最高320万年薪&#xff0c;招聘AIGC方向算法工程师一名。 ChatGPT在全球掀起了AI热潮&#xff0c;国内互联网大厂纷纷加入战局打造国内版ChatGPT。…

ChatGPT催生的高薪职业,竟然会是它?

ChatGPT 的兴起&#xff0c;催生了一个“与众不同”的新职业 —— prompt engineer &#xff08;提示工程师&#xff09;。主要职责是负责为 AI 聊天机器人生成的文本、图片、音频等内容添加关键词和提示&#xff0c;从而指导 AI 聊天机器人根据特定的目标和情境生成更符合用户…

企业高薪招人,近5成岗位月薪过万

据前瞻产业研究院发布的《中国网络游戏行业商业模式创新与投资机会分析报告》显示&#xff1a;2020年&#xff0c;我国网络游戏用户规模达到5.18亿人&#xff0c;市场规模达到2786.9亿元。此外&#xff0c;我国自主研发实力增强&#xff0c;自主研发游戏收入规模持续增长&#…

ChatGPT-5相比ChatGPT-4,将会有哪些变化?

ChatGPT-5 将会2023年12月发布。ChatGPT-5将会是跨时代的版本&#xff0c;将重新彻底引爆GPT。ChatGPT-5相比ChatGPT-4&#xff0c;将会有哪些变化&#xff1f; 最近我创建了一个知识星球&#xff0c;叫【ChatGPT前沿玩法圈】&#xff0c;会把把我玩ChatGPT的经验和总结&#x…

智能GPT结合苹果Siri等于孩子们的十万个为什么,未来已来

引言&#xff1a; 今天是6.1儿童节&#xff0c;我约了朋友&#xff0c;让小朋友们一起到公园玩耍。在玩耍的过程中&#xff0c;我的孩子和其他小朋友时不时地会提出各种问题和疑惑&#xff0c;比如&#xff1a;“为什么四叶草只有三片叶子&#xff1f;”、“为什么长颈鹿要吃骨…

面试碰壁如何力挽狂澜,有了这份Android指南你也可以有绿色通道!

简历怎样写才能过初步筛选&#xff1f;大厂面试到底要求什么&#xff0c;关注什么&#xff1f;技术面试如何展示自己的实力&#xff1f; 95% 的面试者都有这些疑问&#xff0c;所以今天&#xff0c;给大家分享一些面试准备的干货&#xff1a; 一、简历要有含金量 一份漂亮的…

记录一次锁的优化

项目背景 老规矩&#xff0c;先讲讲项目背景。可跳过。 小工具类的微系统。 我们会有一些文本语义描述的事件。譬如某小区两户人家因为宠物发生了争吵&#xff0c;比如某人拨打12345热线反映小区深夜还在跳广场舞等等。这些统称事件。 小学语文老师告诉我们描述事件的叙述文三要…