头像上传
A> MultipartFile接口
MultipartFile接口常用的的API见下表:
方法 | 功能描述 |
---|---|
String getOriginalFilename() | 获取上传文件的原始文件名,即该文件在客户端中的文件名 |
boolean isEmpty() | 判断上传的文件是否为空,当没有选择文件就直接上传,或者选中的文件是0字节的空文件时,返回true,否则返回false |
long getSize() | 获取上传的文件大小,以字节为单位 |
String getContentType() | 根据所上传的文件的扩展名决定该文件的MIME类型,例如上传.jpg格式的图片,将返回image/jpeg |
InputStream getInputStream() | 获取上传文件的输入字节流,通常用于自定义读取所上传的文件的过程,该方法与transferTo()方法不可以同时使用 |
void transferTo(File dest) | 保存上传的文件,该方法与getInputStream()方法不可以同时使用 |
B> MultipartResolver接口
1.MultipartResolver可以将上传过程中产生的数据封装为MultipartFile类型的对象中。
2.在配置MultipartResovler时,可以为其中的几个属性注入值:
- maxUploadSize:上传文件的最大大小,假设设置值为10M,一次性上传5个文件,则5个文件的大小总和不允许超过10M。
- maxUploadSizePerFile:每个上传文件的最大大小,假设设置值为10M,一次性上传5个文件,则每个文件的大小都不可以超过10M,但是5个文件的大小总和可以接近50M。
- defaultEncoding:默认编码。
C> 基于SpringMVC的文件上传案例
3.1 创建项目
1.创建Java Enterprise项目,设置Name为springmvc-upload,Group为com.cy,Artifact为controller的Java企业级项目。
2.将项目com.cy.controller包下自动生成的HelloServlet类删除,并删除webapp下自动生成的index.jsp文件。
3.添加文件上传jar包依赖(关于文件上传需要添加spring-webmvc和commons-fileupload依赖)。
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.3.6.RELEASE</version></dependency><!-- 文件上传 --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency>
</dependencies>
4.在src\main\resources文件夹下创建spring配置文件,并将文件命名为spring-upload.xml。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"></beans>
3.2 前端页面设计
在webapp目录下创建upload.html页面,并在页面中添加如下代码。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>文件上传</title>
</head>
<body><h3>文件上传</h3><!-- enctype属性:规定表单中数据在提交给服务器之前如何进行编码。默认表单数据的编码是"application/x-www-form-urlencoded"。application/x-www-form-urlencoded:提交前表单中所有数据都会进行编码;编码的规则是:空格转换为"+"加号,特殊符号转换为ASCII HEX值text/plain:提交前表单中数据空格转换为"+"加号,但不对特殊字符进行编码。multipart/form-data:提交前表单中不对字符进行编码;在使用包含文件上传控件的表单中,必须使用该值--><form action="upload.do" method="post" enctype="multipart/form-data"><table border="1" cellspacing="0" cellpadding="0"><tr><td>文件名(N):</td><td><p><input type="file" name="file"/></p></td></tr><tr><td colspan="2" align="center"><input type="submit" name="上传"/></td></tr></table></form>
</body>
</html>
注意:form表单的请求方式必须设置为POST,并配置属性enctype=“multipart/form-data”,文件上传input控件的name属性值需设置为file值。
3.3 后台功能实现
1.在web.xml文件中配置前端控制器和过滤器,并指定DispatcherServlet加载的配置文件springmvc-upload.xml的位置。
<servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-upload.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>*.do</url-pattern>
</servlet-mapping><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param>
</filter>
<filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
2.创建com.cy.controller.UploadController控制器类,在类的声明之前添加@Controller注解,并在控制器中添加处理请求的upload()方法,为此方法添加类型为MultipartFile接口的参数,并为该参数添加@RequestParam注解,表示客户端上传的文件。
package com.cy.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;@Controller
public class UploadController {/*@RequestMapping("upload.do")@ResponseBodypublic String upload(@RequestParam("file") MultipartFile file) {System.out.println("UploadController.upload()...");File dest = new File("D:/1.png");try {// 调用MultipartFile参数对象的transferTo()方法即可保存上传的文件file.transferTo(dest);} catch (IOException e) {e.printStackTrace();}return "OK";}*/@RequestMapping("upload.do")@ResponseBodypublic String upload(HttpServletRequest request, @RequestParam("file") MultipartFile file) throws IOException {// 获取上传文件的原始文件名String originalFilename = file.getOriginalFilename();// 获取上下文的绝对路径String realPath = request.getServletContext().getRealPath("upload");System.out.println(realPath);// 创建File文件对象File dir = new File(realPath);if (!dir.exists()) {dir.mkdirs();}// 自定义上传文件名String fileName = UUID.randomUUID().toString();// 获取上传文件扩展名String suffix = "";int beginIndex = originalFilename.lastIndexOf(".");if (beginIndex > 0) {suffix = originalFilename.substring(beginIndex);}String fullFilename = fileName + suffix;// 调用MultipartFile参数对象的transferTo()方法即可保存上传的文件file.transferTo(new File(dir, fullFilename));return "OK";}
}
3.在springmvc-upload.xml配置文件中添加组件扫描和CommonsMultipartResolver类的bean标签配置。
<!-- 组件扫描 -->
<context:component-scan base-package="com.cy" /><!-- CommonsMultipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
注意:CommonsMultipartResolver类在配置时,id值必须设置成multipartResolver。
4.启动项目,访问http://localhost:8080/springmvc_upload_war_exploded/upload.html网址测试文件提交。
1.上传头像-持久层
将对象文件存在操作系统上,然后在把这个文件路径给记录下来,因为在记录路径是非常便捷和方便,将如果要打开文件可以依据这个路径支找到这个文件,在数据中需要保存这个 文件的路径即可,一般情况下将静态资源(图片,文件,其他资源文件)放在某台单独的服务器上
1.1SQL
语句的规划
1.根据uid
查询用户的数据,在上传头像之前,首先要保证当前这个用户的数据存在,检测是否被标记为已经删除,检测输入的原始密码是否正确
select * from t_user where uid = #{uid}
2.上传头像其他就是相关于修改用户的avatar
字段,所以sql
语句是
update t_user set avatar = #{avatar} ,modified_user = #{modifiedUser},modified_tiem = #{modifiedTiem}where uid = #{uid}
1.2设计接口和抽象方法
由于UserMapper
接口已经定义过,所以直接定义抽象方法即可
/*** 用户模块的持久层接口*/
@Mapper
public interface UserMapper extends BaseMapper<User> {/*** 根据uid修改用户头像* @param uid 用户uid* @param avatar 头像路径* @param modifiedUser 修改者* @param modifiedTime 修改时间* @return 受影响行数,如果返回1修改成功,返回0修改失败*/Integer updateAvatarByUid(@Param("uid")Integer uid,@Param("avatar")String avatar,@Param("modifiedUser")String modifiedUser,@Param("modifiedTime")Date modifiedTime);
}
1.3编写映射文件UserMapper.xml
<!-- 根据uid修改用户信息Integer updateAvatarByUid(@Param("uid")Integer uid,@Param("avatar")String avatar,@Param("modifiedUser")String modifiedUser,@Param("modifiedTime")Date modifiedTime);--><update id="updateAvatarByUid">update t_user set avatar = #{avatar},modified_user = #{modifiedUser},modified_time = #{modifiedTime}where uid = #{uid}</update>
1.4 测试
//上传头像@Testvoid updateAvatarByUidTest(){Integer integer = userMapper.updateAvatarByUid(1, "eejeqepcwqin1314168520521", "邓宇瑞", new Date());if (integer==0){System.out.println("上传头像失败!");}else {System.out.println("上传头像成功!");}}
2.上传头像-业务层
2.1 规划异常
1.由于上传前需要先查询该用户是否存在,同时还可以防止用户过长时间不操作,如果不存在直接抛出UserNotFoundException
2.上传头像可以出现上传失败,如果出现上传失败直接抛出updateException
异常
综上:对于这个两种可能出现的异常都已经定义过,所以不需要重新定义
2.2 设计接口和抽象方法
业务层的设计需要参考Mapper
层,由于Mapper
层需要四个参数,并且第四个参数是当前时间Date
,所以这个参数可以直接在业务创建出来。
//处理用户注册
public interface IUserService {/*** 根据用户uid修改用户头像【其实就是上传头像】* @param uid 用户uid* @param username 用户名【也是修改者】* @param avatar 头像路径* @return 如果返回1说明修改成功,返回0说明修改失败*/void changeAvatar(Integer uid,String username,String avatar);
}
2.3 实现抽象方法
//用户模块业务层的实现类
@Service
public class UserServiceImpl implements IUserService {@Autowiredprivate UserMapper userMapper;// 根据用户uid修改头像【其实就是上传头像】@Overridepublic void changeAvatar(Integer uid, String username, String avatar) {// 第一步:先查询该用户是否存在,根据uid查询User user = userMapper.findByUid(uid);// 第二步:判断该用户是否为null或isDelete等于1,如果为null或等于1说明该用户不存在,否则存在if (user==null || user.getIsDelete()==1){throw new UserNotFoundException("该用户不存在!");}// 第三步:调用上传头像方法Integer result = userMapper.updateAvatarByUid(uid, avatar, username, new Date());// 第五步:判断返回值if (result==0){throw new UpdateException("上传头像时出现未知异常!");}}
}
2.4 测试
// 根据uid上传图像@Testvoid changeAvatarTest(){try {userService.changeAvatar(1,"明天","明天131488168");System.out.println("上传成功!");} catch (Exception e) {e.printStackTrace();System.out.println(e.getMessage());System.out.println("上传失败");}}
3.上传头像-控制层
3.1 处理异常
文件异常父类:FileUploadException 泛指文件上传的异常(父类)继承于RuntimeException父类是:FileUploadExceptionFileEmptyException 文件为空的异常FileSizeException 文件大小超出限制异常FileTypeException 文件类型异常FileUploadIoException 文件读写的异常FileStateException 文件状态的异常
1.在处理上传文件的过程中,用户可能会选择错误的文件上传,此时就应该抛出对应的异常并进行处理。所以需要创建文件上传相关异常的基类,即在com.haikang.store.controller.ex包下创建FileUploadException类,并继承自RuntimeException类。
/** 文件上传相关异常的基类 */
public class FileUploadException extends RuntimeException {public FileUploadException() {super();}public FileUploadException(String message) {super(message);}public FileUploadException(String message, Throwable cause) {super(message, cause);}public FileUploadException(Throwable cause) {super(cause);}protected FileUploadException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}
}
2.在处理上传的文件过程中,经分析可能会产生以下异常。这些异常类都需要继承自FileUploadException类。
// 上传的文件为空
FileEmptyException
// 上传的文件大小超出了限制值
FileSizeException
// 上传的文件类型超出了限制
FileTypeException
// 上传的文件状态异常
FileStateException
// 上传文件时读写异常
FileUploadIOException
3.创建FileEmptyException异常类,并继承FileUploadException类。
/** 上传的文件为空的异常,例如没有选择上传的文件就提交了表单,或选择的文件是0字节的空文件 */
public class FileEmptyException extends FileUploadException {// Override Methods...
}
4.创建FileSizeException异常类,并继承FileUploadException类。
/** 上传的文件的大小超出了限制值 */
public class FileSizeException extends FileUploadException {// Override Methods...
}
5.创建FileTypeException异常类,并继承FileUploadException类。
/** 上传的文件类型超出了限制 */
public class FileTypeException extends FileUploadException {// Override Methods...
}
6.创建FileStateException异常类,并继承FileUploadException类。
/** 上传的文件状态异常 */
public class FileStateException extends FileUploadException {// Override Methods...
}
7.创建FileUploadIOException异常类,并继承FileUploadException类。
/** 上传文件时读写异常 */
public class FileUploadIOException extends FileUploadException {// Override Methods...
}
8.在控制器的基类中处理异常
// 控制器类的基类,用于处理异常
@ControllerAdvice
public class BaseController {// 操作成功的状态码:public final static int ok = 200;@ExceptionHandler({ServiceException.class,FileUploadException.class})//表示Service业务层,出现的异常会跳转到该控制器中统一处理public JsonResult<Void> handleException(Throwable e){JsonResult<Void> result = new JsonResult<>();// 文件为空异常if (e instanceof FileEmptyException){result.setState(6001);result.setMessage(e.getMessage());// 文件大小异常}else if (e instanceof FileSizeException){result.setState(6002);result.setMessage(e.getMessage());// 文件状态异常}else if (e instanceof FileStateException){result.setState(6003);result.setMessage(e.getMessage());// 文件类型异常}else if (e instanceof FileTypeException){result.setState(6004);result.setMessage(e.getMessage());// 文件上传时出现异常}else if (e instanceof FileUploadIoException){result.setState(6005);result.setMessage(e.getMessage());}return result;}}
注意是:必须要在异常处理方法上添加FileUploadException.class
表示也可以处理FileUploadException
类型的异常
@ExceptionHandler({ServiceException.class,FileUploadException.class})//表示Service业务层,出现的异常会跳转到该控制器中统一处理
3.2 设计请求
请求路径 url: "http://localhost/users/change_avatar"
请求参数 data: MultipartFile file,HttpSession session
请求类型 type: POST
响应结果 JsonResult<String>
3.3 处理请求
@RestController
@RequestMapping("users")
public class UserController extends BaseController{@AutowiredIUserService userService;// 第一步:规定文件大小public static final int AVATAR_MAX_SIZE = 20 * 1024 * 1024;// 第二步:允许上传的头像的文件类型public static final List<String> AVATAR_TYPES = new ArrayList<>();// 第三步:初始化上传的文件类型static {AVATAR_TYPES.add("image/jpeg");AVATAR_TYPES.add("image/png");AVATAR_TYPES.add("image/bmp");AVATAR_TYPES.add("image/gif");}/*** 文件上传功能* @param session session对象用于获取用户uid和username* @param file 文件* @return 响应文件路径和状态** MultipartFile接口是SpringMVC提供一个接口,这个 接口为我们包装了* 获取文件类型的数据(任何类型的file文件都可以接收),SpringBoot它有整合了* SpringMVC,只需要在处理请求的方法参数列表上声明一个参数为MultipartFiler的参数,然后* SpringBoot自动将传递给文件数据赋值给这个参数*/@RequestMapping("change_avatar")public JsonResult<String> changeAvatar(HttpSession session,@RequestParam("file")MultipartFile file){// 判断文件是否为空if (file.isEmpty()){throw new FileEmptyException("上传的头像文件不允许为空!");}// 判断文件的大小if (file.getSize()>AVATAR_MAX_SIZE){throw new FileSizeException("不允许上传文件大小超过"+(AVATAR_MAX_SIZE/1024)+"KB的头像文件!");}// 判断上传文件的类型是否正确// 1.获取文件类型String fileContentType = file.getContentType();// 2.如果不包含,直接抛出异常if (!AVATAR_TYPES.contains(fileContentType)){throw new FileTypeException("不支持使用该类型的文件作为头像,允许的文件类型:\n" + AVATAR_TYPES);}// 获取当前项目的绝对磁盘路径String parent = session.getServletContext().getRealPath("upload");// 判断保存头像文件的文件夹是否存在,如果不存在则创建File dir = new File(parent);if (!dir.exists()){// 创建upload文件夹dir.mkdirs();}// 保存头像文件的文件名// 返回文件名:例如:eeje.jpg[包含文件类型就是`.jpg`]String originalFilename = file.getOriginalFilename();// 获取文件后缀,就是获取最后一个`.` 的索引,开始截取int lastIndexOf = originalFilename.lastIndexOf(".");// 截取出后缀 例如:.jpgString suffix = originalFilename.substring(lastIndexOf);// 拼接出随机文件名,防止文件名重复String fileName = UUID.randomUUID().toString()+suffix;// 创建文件对象,表示保存的头像文件File dest = new File(dir,fileName);// 执行保存头像文件try {file.transferTo(dest);}catch (FileStateException e){throw new FileStateException("文件状态异常,可能文件已经被移动或删除!");} catch (IOException e) {throw new FileUploadIoException("上传文件时读写错误,请稍后重尝试!");}// 执行UserService文件保存头像路径// 头像路径String avatar = "/upload/"+fileName;// 注意是:一定不能少掉`/`,该表示当前项目的根路径// 从Session中获取uid和usernameInteger uid = getUidFromSession(session);String username = getUserNameFromSession(session);// 将头像写入到数据库中userService.changeAvatar(uid,username,avatar);// 返回成功头像路径return new JsonResult<>(ok,avatar);}}
4.上传头像-页面
在upload
页面中编写上传头像的代码
说明:如果直接使用表单进行文件的上传,需要给表单显示的添加一个属性
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="../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>
表单必须满足下面三个属性
<form class="form-horizontal" action="/users/change_avatar"method="post"enctype="multipart/form-data"role="form">
</form>
用户-上传头像-设置上传文件大小
1.在SpringBoot
中默认MultipartResolver
的最大文件大小值为1M
。如果上传的文件超过1M
,会就抛出FileSizeLimitExceededException
异常
解析方式一:使用Java
代码的方式
如果在需要调整上传的限制值,直接在主启动类
中添加getMultipartConfigElement()
方法,并且使用@Bean
标记.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;import javax.servlet.MultipartConfigElement;@SpringBootApplication
public class StoreApplication {public static void main(String[] args) {SpringApplication.run(StoreApplication.class, args);}@Beanpublic MultipartConfigElement getMultipartConfigElement() {MultipartConfigFactory factory = new MultipartConfigFactory();// DataSize dataSize = DataSize.ofMegabytes(10);// 设置文件最大10M,DataUnit提供5中类型B,KB,MB,GB,TBfactory.setMaxFileSize(DataSize.of(10, DataUnit.MEGABYTES));factory.setMaxRequestSize(DataSize.of(10, DataUnit.MEGABYTES));// 设置总上传数据总大小10Mreturn factory.createMultipartConfig();}
}
解析方式二:使用配置文件
方式
yaml
方式:
spring:servlet:multipart:max-file-size: 20MB #上传文件的最大大小max-request-size: 25MB #最大请求大小
properties
方式:
#方式1
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
#方式2
spring.servlet.multipart.maxFileSize=10MB
spring.servlet.multipart.maxRequestSize=10MB
回显头像
注意是:在ajax
请求中<input type="submit" />
具有自动提交的功能,所以在使用ajax
发送请求时,需要将<input type="button" />
在页面中通过ajax
请求来提交文件,提交完成后返回json
字符串,解析出data
中数据,设置到img
头像标签的src
属性上就可以了:
-
serialize()
:可以将表单数据自动拼接成key=value
的结构进行提交给服务器,一般提交是普通的控件类型中的数据,如text \ password \ radio \ checkbox
等 -
FormData
类:将表单中的数据保持原有的结构进行数据提交 -
如: new FormData($("#form")[0]); // 文件类型的数据可以使用`FormData`对象进行存储,注意是:`FormData($("#form")[0])`表示是第一个控件
-
ajax
默认处理数据时按照字符串形式处理,以及默认会采用字符串形式进行提交数据,关闭这两个默认功能 -
processData: false, // processData处理数据 , 关闭处理数据 contentType: false, // contentType发送数据格式 ,关闭默认提交数据的形式
总结:在
JQuery
中
val
方法是:可以获取到文本的值,并且可以修改文件中的值,如:修改组件中的文件值
attr
和prop
区别?
1.如果操作的是元素的固有属性,则建议使用prop【就是系统定义的属性】
2.如果操作的是元素自定义的属性,则建议使用attr
1.修改表单中提交组件
成按钮
<!--上传头像表单开始--><form class="form-horizontal"id="form-change-avatar"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="../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="button" id="btn-change-avatar" class="btn btn-primary" value="上传" /></div></div></form>
2.发送ajax
请求
<!--页脚结束--><script type="text/javascript">$("#btn-change-avatar").click(function () {$.ajax({url: "http://localhost/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("修改成功!");$("#img-avatar").attr("src",json.data);}else {alert("修改失败!")}},error: function (xhr) {alert(xhr.status+"-----"+xhr.message);}});});</script>
回显头像总结:
上传后显示头像
1.头像上传成功后,显示上传的头像。在upload.html页面中,是使用img标签来显示头像图片的。首先确定img标签是否添加有id="img-avatar"属性,便于后续访问该标签;而img标签是通过src属性来决定显示哪张图片的,所以修改src该属性的值即可设置需要显示的图片。修改表单添加id="form-change-avatar"属性。修改input标签,添加id="btn-change-avatar"和type="button"属性。
2.在upload.html页面中body标签内部的最后,添加script标签用于编写JavaScript程序。
- 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) {$("#img-avatar").attr("src", json.data);} else {alert("修改失败!" + json.message);}},error: function(xhr) {alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + xhr.status);location.href = "login.html";}});});
</script>
3.完成后启动项目,打开浏览器先登录,再访问http://localhost:80/web/upload.html进行测试。
登录后显示头像【重点】
可以更新头像成功后,将服务器返回的头像路径保存在客户端cookie
对象,然后每次检测到用户打开上传头像页面,在这个页面通过ready()
方法来自动检测去读取cookie
中头像并设到src
属性上。
在页面中设置cookie
步骤:
第一步:导入cookie.js
文件
<script src="../bootstrap3/js/jquery.cookie.js" type="text/javascript" charset="utf-8"></script>
第二步:调用cookie
方法:
$.cookie(key,value,time); // time单位为:天
登录后显示图片步骤:
第一步:导入cookie.js
文件
<script src="../bootstrap3/js/jquery.cookie.js" type="text/javascript" charset="utf-8"></script>
第二步:在login.html
页面设置cookie
的值
<!--页脚结束--><script type="text/javascript">// 第一步:监听按钮$("#btn-login").click(function () {$.ajax({url: "http://localhost:80/users/login",type: "POST",dataType: "JSON",data: $("#form-login").serialize(),success: function (json) {if (json.state == 200){alert("登录成功!");}// 将服务器返回头像设置到cookie中$.cookie("avatar",json.data.avatar,{expires: 7}); // 表示将cookie存活时间设置为7天location.href = "http://localhost:80/web/index.html";},error: function (xhr) {alert("登录失败!"+xhr.status);}});});</script>
第三步:在upload.html
页面,导入cookie.js
文件
<script src="../bootstrap3/js/jquery.cookie.js" type="text/javascript" charset="utf-8"></script>
第四步:在upload.html
页面,调用ready()
方法自动读取cookie
中的值
<!--页脚结束--><script type="text/javascript">// 调用 ready 方法读取cookie的值$(document).ready(function () {let avatar = $.cookie("avatar");// 将cookie值获取出来设置到头像src属性中$("#img-avatar").attr("src", $.cookie("avatar"));});</script>
显示最新的头像:
在更新头像后,将最新的头像地址,再次保存到cookie
中,同名保存会覆盖原来的cookie
值
<!--页脚结束--><script type="text/javascript">// 调用 ready 方法读取cookie的值$(document).ready(function () {let avatar = $.cookie("avatar");// 将cookie值获取出来设置到头像src属性中$("#img-avatar").attr("src", $.cookie("avatar"));});// 第一步:监听按钮$("#btn-login").click(function () {$.ajax({url: "http://localhost:80/users/login",type: "POST",dataType: "JSON",data: $("#form-login").serialize(),success: function (json) {if (json.state == 200){alert("登录成功!");}// 将服务器返回头像设置到cookie中,如果重新上传了新头像,则将新的头像`路径`保存到cookie中$.cookie("avatar",json.data.avatar,{expires: 7}); // 表示将cookie存活时间设置为7天location.href = "http://localhost:80/web/index.html";},error: function (xhr) {alert("登录失败!"+xhr.status);}});});</script>
总结:
登录显示头像
1.首先检查登录成功后是否返回了头像的数据。访问http://localhost:8080/users/login?username=admin&password=321测试。
2.用户名、用户Id、用户头像等数据,属于常用数据,在客户端的许多页面都可能需要使用,如果每次都向服务器提交请求获取这些数据,是非常不合适的。可以在用户登录成功后,将这些数据存储在客户端本地,后续在客户端中需要显示这些数据时,直接从本地获取即可,无需再向服务器请求这些数据。在客户端本地存取数据时,可以使用Cookie技术。
3.设计思路:当用户登录成功后,将服务器返回的头像路径存储到本地的Cookie中,在打开“上传头像”页面时,从本地的Cookie中读取头像路径并显示即可。在登录login.html页面中,当登录成功后,将用户头像路径保存到Cookie中。
$("#btn-login").click(function() {$.ajax({url: "/users/login",type: "POST",data: $("#form-login").serialize(),dataType: "json",success: function(json) {if (json.state == 200) {alert("登录成功!");$.cookie("avatar", json.data.avatar, {expires: 7});console.log("cookie中的avatar=" + $.cookie("avatar"));location.href = "index.html";} else {alert("登录失败!" + json.message);}}});
});
语法:$.cookie(名称,值,[option])。[option]参数说明:
expires:有限日期,可以是一个整数或一个日期(单位天)。如果不设置这个值,默认情况下浏览器关闭之后此Cookie就会失效。
path:表示Cookie值保存的路径,默认与创建页路径一致。
domin:表示Cookie域名属性,默认与创建页域名一样。要注意跨域的概念,如果要主域名二级域名有效则要设置“.xxx.com”。
secrue:布尔类型的值,表示传输Cookie值时,是否需要一个安全协议。
4.在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>
5.在打开页面时自动读取显示用户图像。获取Cookie中头像的路径,然后将获取到的头像路径设置给img标签的src属性以显示头像。在upload.html页面中的script标签的内部添加自动读取用户图像的jquery代码。
$(document).ready(function () {console.log("cookie中的avatar=" + $.cookie("avatar"));$("#img-avatar").attr("src", $.cookie("avatar"));
});
显示最新头像
以上代码表示“每次打开页面时,读取Cookie中的头像并显示”,如果此时重新上传用户头像,而Cookie中所保存的头像还是之前上传的头像路径值,无法显示最新的用户头像。所以当用户重新上传头像后,还应把新头像的路径更新到Cookie中。
1.在upload.html页面中,用户头像修改成功后,并将新的用户头像路径保存到Cookie中。
$.cookie("avatar", json.data, {expires: 7});
2.完成后启动项目,打开浏览器先登录,再访问http://localhost:8080/web/upload.html进行测试。