Spring文件上传
关于CommonsMultipartFile类
String getContentType():返回文件的MIME类型,例如
image/jpeg
String getOriginalFileName():获取原始文件文件,例如
a.jpg
long size():获取文件大小,以字节为单位
关于配置CommonsMultipartResolver
maxUploadSize:上传的文件的最大尺寸,假设设置值为1M,如果单次上传了10个文件,只要总和不超过1M则可以正常上传
maxUploadSizePerFile:上传的文件中,每个文件的最大尺寸,假设设置值为1M,如果单次上传10个文件,每个文件都不超过1M即可,而总共上传的数据可以接近10M
关于一次性上传多个文件
首先,在页面的上传的控件中,必须添加multiple="multiple"
才可以同时选中多个文件:
<input type="file" name="file" multiple="multiple" />
然后,在Spring的控制器中,参数应该使用数组,即CommonsMultipartFile[] file
来处理。
关于AJAX上传
基于jQuery的AJAX上传,首先,应该为上传控件所在的<form>
分配id,然后,,在上传之前,通过var data = new FormData($("#form-id")[0]);
获取数据,并且,在调用的$.ajax()
函数中,需要添加"contentType": false
和"processData": false
这2项配置:
$("#ajax_upload").click(function() {
var url = "upload.do";
var data = new FormData($("#upload-form")[0]);
$.ajax({
"url": url,
"data": data,
"type": "post",
"dataType": "json",
"contentType": false,
"processData": false,
"success": function(json) {
console.log("success");
}
});
});
关于处理同一个表单中的其它数据
在上传时,如果表单中还包括其它数据也会提交,处理方式与普通请求相同,即在服务端的控制器中,在处理请求的方法上添加同名参数,或者使用对象来接收数据都是可以的,而前端的提交方式可以不用发生变化,如果是使用<form>
和<input type="submit" />
,会把表单中的数据全部提交,如果是使用var data = new FormData($("#form-id")[0]);
也会把表单中的数据全部提交。
5. 用户-修改个人信息
5.4. 头像上传
首先,在前端页面,上传头像的控件调整为:
<input type="file" name="avatar" />
并且,在提交AJAX请求之前,提交的数据调整为:
var data = new FormData($("#user_info")[0]);
然后,在提交的AJAX请求中,添加:
"contentType": false,
"processData": false,
在服务端的处理中,首先,应该添加依赖:
<!-- 文件上传 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
然后,在Spring的配置文件中添加配置:
<!-- 配置CommonsMultipartResolver -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="900000" />
<property name="defaultEncoding" value="utf-8" />
</bean>
然后,在控制器处理请求时,添加CommonsMultipartFile
参数:
@RequestMapping(value="/handle_change_info.do")
@ResponseBody
public ResponseResult<String> handleChangeInfo(
User user, HttpServletRequest request,
@RequestParam CommonsMultipartFile avatarFile,
HttpSession session) {
// 判断用户名和邮箱,如果为"",则设为null
// 也可以用正则表达式来判断
if ("".equals(user.getUsername())) {
user.setUsername(null);
}
if ("".equals(user.getEmail())) {
user.setEmail(null);
}
// 判断此次操作是否上传了头像
if (!avatarFile.isEmpty()) {
// 上传头像,并获取上传后的路径
String avatarPath = uploadAvatar(
request, avatarFile);
// 把头像文件的路径封装,以写入到数据表中
user.setAvatar(avatarPath);
}
// 从session获取uid
Integer uid = getUidFromSession(session);
// 将uid封装到参数user中
user.setId(uid);
// 执行修改:userService.changeInfo(user)
userService.changeInfo(user);
// 返回
ResponseResult<String> rr
= new ResponseResult<String>();
rr.setData(user.getAvatar());
return rr;
}
/**
* 上传头像
* @param request HttpServletRequest
* @param avatarFile CommonsMultipartFile
* @return 成功上传后,文件保存到的路径
* @throws UploadAvatarException 上传头像异常
*/
private String uploadAvatar(
HttpServletRequest request,
CommonsMultipartFile avatarFile)
throws UploadAvatarException {
// 确定头像保存到的文件夹的路径:项目根目录下的upload文件夹
String uploadDirPath
= request.getServletContext()
.getRealPath("upload");
// 确定头像保存到的文件夹
File uploadDir = new File(uploadDirPath);
// 确保文件夹存在
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
// 确定头像文件的扩展名,例如:aaa.bbb.ccc.jpg,所需的是.jpg
int beginIndex = avatarFile.getOriginalFilename()
.lastIndexOf(".");
String suffix = avatarFile.getOriginalFilename()
.substring(beginIndex);
// 确定头像文件的文件名,必须唯一
String fileName = UUID.randomUUID().toString() + suffix;
// 确定头像保存到哪个文件
File dest = new File(uploadDir, fileName);
// 保存头像文件
try {
avatarFile.transferTo(dest);
return "upload/" + fileName;
} catch (IllegalStateException e) {
throw new UploadAvatarException(
"非法状态!");
} catch (IOException e) {
throw new UploadAvatarException(
"读写出错!");
}
}
5.5. 默认显示当前用户数据
当前页面是HTML页面(不是jsp),HTML页面是运行在客户端的浏览器的,所以,无法通过转发显示数据,也无法直接显示Session中的数据!
所以,在HTML页面中,如果需要显示来自于服务器的数据,应该发出AJAX请求,获取对应的数据,然后通过JavaScript将这些数据填充到某些标签中,以此完成显示!
为了实现个人信息页面中显示相关数据,还是与此前的开发流程一致,即:持久层 > 业务层 > 控制器层 > 前端页面,此次的目标是“显示当前登录的用户信息”,并且,是用户已经登录之后(Session中已经有当前用户的uid)的操作,所以,根据uid获取用户信息,并把信息响应给客户端即可!
而“根据uid获取用户信息”在此前的功能开发中已经实现,在持久层和业务层均已经实现User getUserById(Integer uid)
方法,所以,此次无须再开发持久层和业务层,直接开发控制器层和前端页面即可!
接下来,设计用户提交的请求:
请求路径:/user/getInfo.do
请求类型:GET
请求参数:无
响应方式:ResponseResult<User>
是否拦截:是,登录拦截,已经拦截/user/**,所以,无须修改配置
所以,在UserController.java
中添加处理请求的方法:
@RequestMapping("/getInfo.do")
@ResponseBody
public ResponseResult<User> getInfo(HttpSession session) {
// 从session中获取uid
// 调用业务层对象的getUserById(),得到当前用户的User数据
// 创建返回值对象,将User对象封装到Data属性中
// 返回
}
然后,测试,需先登录,然后通过http://localhost:8080/xxx/user/getInfo.do
进行测试。
其它
1. ArrayList和LinkedList
ArrayList
是基于数组来实现的,而LinkedList
是基于链表来实现的!
基于它们的存储特征,所以:ArrayList
的查询非常方便,但是新增、删除、插入操作的效率都很低!LinkedList
的查询效率很低,但是新增、删除、插入操作的效率都很高!
注意:ArrayList和LinkedList没有继承关系,不可以随时转换数据类型,即ArrayList不可以转成LinkedList,反之,也是不可以的!