1、前端上传文件
(1)表单上传文件
略:
(2)JQuery上传文件
略:
注:如果是使用JQuery上传文件,那么在后端的文件接收参数中要使用要使用@RequestParam("name")指定前端的对应参数名,否则可能会无法接收到文件,例如:JQuery上传文件时,文件对应的参数名是“files”,那么在后端也要用@RequestParam("files")修饰接收文件的参数。
2、后端接收和保存
案例代码中,Api开头的注解可以去掉,与上传逻辑没有关系。
@ApiOperation(value = "更换用户头像", notes = "更换用户头像接口", httpMethod = "POST")
@PostMapping("uploadFace")
public IMOOCJSONResult uploadFace(@ApiParam(value = "用户Id", name = "userId", required = true)
@RequestParam String userId,
@ApiParam(value = "用户头像文件", name = "file", required = true)
MultipartFile file,
HttpServletRequest request, HttpServletResponse response){
if(StringUtils.isBlank(userId)){
IMOOCJSONResult.errorMsg("用户Id不能为空");
}
// 定义头像保存地址
String fileSpce = uploadResource.getImageUserFaceUploadSpace();
// 在路径上为每个用户添加userId,用于区分不同的用户上传
String uploadPathPrefix = File.separator + userId;
String userFaceServiceUrl = uploadResource.getUserServiceUrlPrefix();
// 文件开始上传
if(file != null){
FileOutputStream outputStream = null;
try {
String fileName = file.getOriginalFilename();
if(StringUtils.isNotBlank(fileName)){
String[] fileNameArr = fileName.split("\\.");
String suffix = fileNameArr[fileNameArr.length - 1];
if(!suffix.equalsIgnoreCase("jpg") && !suffix.equalsIgnoreCase("jpeg")
&& !suffix.equalsIgnoreCase("png")){
return IMOOCJSONResult.errorMsg("图片格式不正确");
}
// 创建文件名称
String newFileName = File.separator + "face_" + userId + "." + suffix;
// 头像的访问路径
userFaceServiceUrl += (userId + "/" + "face_" + userId + "." + suffix + "?gt=" + System.currentTimeMillis());
File newFile = new File(fileSpce + uploadPathPrefix + newFileName);
if(newFile.getParentFile() != null){
// 创建文件夹
newFile.getParentFile().mkdirs();
}
// 上传文件-保存文件
outputStream = new FileOutputStream(newFile);
InputStream inputStream = file.getInputStream();
IOUtils.copy(inputStream, outputStream);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(outputStream != null){
outputStream.flush();
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
return IMOOCJSONResult.errorMsg("用户头像不能为空");
}
// 更新数据库用户头像地址
Users users = centerUserService.updateUserFace(userId,userFaceServiceUrl);
// 脱敏处理
users = setNullProperty(users);
CookieUtils.setCookie(request, response, "user", JsonUtils.objectToJson(users), true);
return IMOOCJSONResult.ok(users);
}
文件分隔符:上面的代码中,文件路径并未使用“/”、“\\”等符号进行分隔,而是使用File.separator对文件进行分隔,因为项目在不同的系统上运行,文件分隔符是不一样的,一旦写死,在更换系统的时候,还要修改程序中的代码,很不方便,使用File.separator,会自动根据系统而使用对应的文件分隔符。
文件类型判断:上面的代码中,在拿到文件类型的时候,对类型进行了判断,这是为了防止有人上传.sh/bat等脚本文件,对系统进行恶意操作。
文件的网络地址:在添加文件的时候,要同时生成文件的网络请求地址,但是在地址的后边,添加了一个gt参数,这个参数值是当前时间戳,添加这个参数是因为,浏览器会对静态资源进行缓存,如果我们更换头像之后,没有对头像的请求地址添加这个参数,那么请求地址和原来的地址是一样的,那么很有可能,头像更换之后,浏览器在刷新页面之后,显示的头像还是原来的(浏览器直接从缓存中获取头像),但是我们添加这个参数之后,头像地址和原来的头像地址就不一样了,浏览器便会从浏览器请求头像文件。静态资源提供网络映射服务。
3、上传文件大小限制以及自定义捕获异常
上传文件大小限制
spring:
servlet:
multipart:
max-file-size: 512000 #上传文件大小限制
max-request-size: 512000 #请求大小限制
一旦上传文件超过指定的最大值,程序就会抛出异常,因为这程序和异常并不是我们自己定义的,所以没办法直接捕获处理,需要使用@RestControllerAdvice或者@ControllerAdvice(取决于对应的controller用的哪个注解)
自定义捕获异常
@RestControllerAdvice
public class CostumExceptionHandler {
// 上传文件超过500K异常捕获:MaxUploadSizeExceededException
@ExceptionHandler(MaxUploadSizeExceededException.class)
public IMOOCJSONResult maxFileUpload(MaxUploadSizeExceededException e){
return IMOOCJSONResult.errorMsg("上传文件不能超过500K,请压缩图片或者降低图片质量在上传");
}
}