优化头像上传

This commit is contained in:
none 2023-03-24 14:59:42 +08:00
parent 82ad3cc28a
commit 639f3065a2
12 changed files with 341 additions and 19 deletions

View File

@ -15,4 +15,11 @@ public class FrontendConstant {
add("/api/v1/auth/login/password");
}};
public final static String USER_UPLOAD_IMAGE_TYPE_AVATAR = "avatar";
public final static String USER_UPLOAD_IMAGE_SCENE_AVATAR = "avatar";
public final static String DIR_AVATAR = "user/avatar/";
}

View File

@ -5,11 +5,10 @@ import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import xyz.playedu.api.FCtx;
import xyz.playedu.api.domain.Course;
import xyz.playedu.api.domain.Department;
import xyz.playedu.api.domain.User;
import xyz.playedu.api.domain.UserCourseRecord;
import xyz.playedu.api.constant.FrontendConstant;
import xyz.playedu.api.domain.*;
import xyz.playedu.api.exception.ServiceException;
import xyz.playedu.api.request.frontend.ChangePasswordRequest;
import xyz.playedu.api.service.*;
@ -42,6 +41,9 @@ public class UserController {
@Autowired
private UserLearnDurationStatsService userLearnDurationStatsService;
@Autowired
private UploadService uploadService;
@GetMapping("/detail")
public JsonResponse detail() {
User user = FCtx.getUser();
@ -55,7 +57,9 @@ public class UserController {
}
@PutMapping("/avatar")
public JsonResponse changeAvatar() {
public JsonResponse changeAvatar(MultipartFile file) {
UserUploadImageLog log = uploadService.userAvatar(FCtx.getUserId(), file, FrontendConstant.USER_UPLOAD_IMAGE_TYPE_AVATAR, FrontendConstant.USER_UPLOAD_IMAGE_SCENE_AVATAR);
userService.changeAvatar(FCtx.getUserId(), log.getUrl());
return JsonResponse.success();
}
@ -67,7 +71,6 @@ public class UserController {
@GetMapping("/courses")
public JsonResponse courses(@RequestParam HashMap<String, Object> params) {
Integer isRequired = MapUtils.getInteger(params, "is_required");
Integer depId = MapUtils.getInteger(params, "dep_id");
if (depId == null || depId == 0) {
return JsonResponse.error("请选择部门");

View File

@ -0,0 +1,137 @@
package xyz.playedu.api.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
*
* @TableName user_upload_image_logs
*/
@TableName(value ="user_upload_image_logs")
@Data
public class UserUploadImageLog implements Serializable {
/**
*
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
*
*/
@JsonProperty("user_id")
private Integer userId;
/**
* 图片类型
*/
private String typed;
/**
* 上传场景
*/
private String scene;
/**
* 驱动
*/
private String driver;
/**
* 相对路径
*/
private String path;
/**
* 访问地址
*/
private String url;
/**
* 大小,单位:字节
*/
private Long size;
/**
* 文件名
*/
private String name;
/**
*
*/
@JsonProperty("created_at")
private Date createdAt;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
UserUploadImageLog other = (UserUploadImageLog) that;
return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
&& (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId()))
&& (this.getTyped() == null ? other.getTyped() == null : this.getTyped().equals(other.getTyped()))
&& (this.getScene() == null ? other.getScene() == null : this.getScene().equals(other.getScene()))
&& (this.getDriver() == null ? other.getDriver() == null : this.getDriver().equals(other.getDriver()))
&& (this.getPath() == null ? other.getPath() == null : this.getPath().equals(other.getPath()))
&& (this.getUrl() == null ? other.getUrl() == null : this.getUrl().equals(other.getUrl()))
&& (this.getSize() == null ? other.getSize() == null : this.getSize().equals(other.getSize()))
&& (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()))
&& (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt()));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode());
result = prime * result + ((getTyped() == null) ? 0 : getTyped().hashCode());
result = prime * result + ((getScene() == null) ? 0 : getScene().hashCode());
result = prime * result + ((getDriver() == null) ? 0 : getDriver().hashCode());
result = prime * result + ((getPath() == null) ? 0 : getPath().hashCode());
result = prime * result + ((getUrl() == null) ? 0 : getUrl().hashCode());
result = prime * result + ((getSize() == null) ? 0 : getSize().hashCode());
result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode());
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", userId=").append(userId);
sb.append(", typed=").append(typed);
sb.append(", scene=").append(scene);
sb.append(", driver=").append(driver);
sb.append(", path=").append(path);
sb.append(", url=").append(url);
sb.append(", size=").append(size);
sb.append(", name=").append(name);
sb.append(", createdAt=").append(createdAt);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();
}
}

View File

@ -0,0 +1,20 @@
package xyz.playedu.api.mapper;
import org.apache.ibatis.annotations.Mapper;
import xyz.playedu.api.domain.UserUploadImageLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author tengteng
* @description 针对表user_upload_image_logs的数据库操作Mapper
* @createDate 2023-03-24 14:32:48
* @Entity xyz.playedu.api.domain.UserUploadImageLog
*/
@Mapper
public interface UserUploadImageLogMapper extends BaseMapper<UserUploadImageLog> {
}

View File

@ -2,14 +2,21 @@ package xyz.playedu.api.service;
import org.springframework.web.multipart.MultipartFile;
import xyz.playedu.api.domain.Resource;
import xyz.playedu.api.domain.UserUploadImageLog;
import xyz.playedu.api.exception.ServiceException;
import xyz.playedu.api.types.UploadFileInfo;
/**
* @Author 杭州白书科技有限公司
* @create 2023/3/8 14:02
*/
public interface UploadService {
UploadFileInfo upload(MultipartFile file, String dir) throws ServiceException;
Resource storeMinio(Integer adminId, MultipartFile file, String categoryIds) throws ServiceException;
Resource storeBase64Image(Integer adminId, String content, String categoryIds) throws ServiceException;
UserUploadImageLog userAvatar(Integer userId, MultipartFile file, String typed, String scene);
}

View File

@ -47,4 +47,6 @@ public interface UserService extends IService<User> {
Long yesterdayCount();
Map<Integer, List<Integer>> getDepIdsGroup(List<Integer> userIds);
void changeAvatar(Integer userId, String avatar);
}

View File

@ -0,0 +1,13 @@
package xyz.playedu.api.service;
import xyz.playedu.api.domain.UserUploadImageLog;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author tengteng
* @description 针对表user_upload_image_logs的数据库操作Service
* @createDate 2023-03-24 14:32:48
*/
public interface UserUploadImageLogService extends IService<UserUploadImageLog> {
}

View File

@ -1,18 +1,25 @@
package xyz.playedu.api.service.impl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import xyz.playedu.api.constant.BackendConstant;
import xyz.playedu.api.constant.FrontendConstant;
import xyz.playedu.api.domain.Resource;
import xyz.playedu.api.domain.UserUploadImageLog;
import xyz.playedu.api.exception.ServiceException;
import xyz.playedu.api.service.MinioService;
import xyz.playedu.api.service.ResourceService;
import xyz.playedu.api.service.UploadService;
import xyz.playedu.api.service.UserUploadImageLogService;
import xyz.playedu.api.types.UploadFileInfo;
import xyz.playedu.api.util.Base64Util;
import xyz.playedu.api.util.HelperUtil;
import java.util.Date;
/**
* @Author 杭州白书科技有限公司
* @create 2023/3/8 14:02
@ -27,34 +34,69 @@ public class UploadServiceImpl implements UploadService {
@Autowired
private MinioService minioService;
@Autowired
private UserUploadImageLogService userUploadImageLogService;
@Override
public Resource storeMinio(Integer adminId, MultipartFile file, String categoryIds) throws ServiceException {
@SneakyThrows
public UploadFileInfo upload(MultipartFile file, String dir) {
if (file == null || file.isEmpty() || file.getOriginalFilename() == null) {
throw new ServiceException("请上传文件");
}
// 文件后缀名校验
// 上传上来的文件名名
String filename = file.getOriginalFilename();
String ext = HelperUtil.fileExt(filename);
String type = BackendConstant.RESOURCE_EXT_2_TYPE.get(ext);
if (type == null) {
UploadFileInfo fileInfo = new UploadFileInfo();
// 文件大小
fileInfo.setSize(file.getSize());
// 解析扩展名
fileInfo.setExtension(HelperUtil.fileExt(filename));
// 解析扩展名称对应的系统资源类型
fileInfo.setResourceType(BackendConstant.RESOURCE_EXT_2_TYPE.get(fileInfo.getExtension()));
// 检测是否为系统不支持的资源类型
if (fileInfo.getResourceType() == null) {
throw new ServiceException("当前资源扩展不支持上传");
}
// 上传原文件的文件名
String oFilename = filename.replaceAll("." + ext, "");
fileInfo.setOriginalName(filename.replaceAll("." + fileInfo.getExtension(), ""));
// 自定义新的存储文件名
String newFilename = HelperUtil.randomString(32) + "." + ext;
String savePath = BackendConstant.RESOURCE_TYPE_2_DIR.get(type) + newFilename;
fileInfo.setSaveName(HelperUtil.randomString(32) + "." + fileInfo.getExtension());
// 生成保存的相对路径
if (dir == null || dir.length() == 0) {
dir = BackendConstant.RESOURCE_TYPE_2_DIR.get(fileInfo.getResourceType());
}
fileInfo.setSavePath(dir + fileInfo.getSaveName());
// 保存文件并生成访问url
String url = minioService.saveFile(file, fileInfo.getSavePath(), BackendConstant.RESOURCE_EXT_2_CONTENT_TYPE.get(fileInfo.getExtension()));
fileInfo.setUrl(url);
// 保存文件
String url = minioService.saveFile(file, savePath, BackendConstant.RESOURCE_EXT_2_CONTENT_TYPE.get(ext));
// 上传记录
return resourceService.create(adminId, categoryIds, type, oFilename, ext, file.getSize(), BackendConstant.STORAGE_DRIVER_MINIO, "", savePath, url);
return fileInfo;
}
@Override
public Resource storeBase64Image(Integer adminId, String content, String categoryIds) throws ServiceException {
@SneakyThrows
public Resource storeMinio(Integer adminId, MultipartFile file, String categoryIds) {
UploadFileInfo info = upload(file, null);
return resourceService.create(
adminId,
categoryIds,
info.getResourceType(),
info.getOriginalName(),
info.getExtension(),
file.getSize(),
BackendConstant.STORAGE_DRIVER_MINIO,
"",
info.getSavePath(),
info.getUrl()
);
}
@Override
@SneakyThrows
public Resource storeBase64Image(Integer adminId, String content, String categoryIds) {
// data:image/jpeg;base64,
String[] base64Rows = content.split(",");
// 解析出content-type
@ -77,4 +119,21 @@ public class UploadServiceImpl implements UploadService {
// 上传记录
return resourceService.create(adminId, categoryIds, type, filename, ext, (long) binary.length, BackendConstant.STORAGE_DRIVER_MINIO, "", savePath, url);
}
@Override
@SneakyThrows
public UserUploadImageLog userAvatar(Integer userId, MultipartFile file, String typed, String scene) {
UploadFileInfo info = upload(file, FrontendConstant.DIR_AVATAR);
UserUploadImageLog log = new UserUploadImageLog();
log.setUserId(userId);
log.setTyped(typed);
log.setScene(scene);
log.setDriver(BackendConstant.STORAGE_DRIVER_MINIO);
log.setPath(info.getSavePath());
log.setUrl(info.getUrl());
log.setName(info.getOriginalName());
log.setCreatedAt(new Date());
userUploadImageLogService.save(log);
return log;
}
}

View File

@ -204,6 +204,14 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
});
return result;
}
@Override
public void changeAvatar(Integer userId, String avatar) {
User user = new User();
user.setId(userId);
user.setAvatar(avatar);
updateById(user);
}
}

View File

@ -0,0 +1,22 @@
package xyz.playedu.api.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import xyz.playedu.api.domain.UserUploadImageLog;
import xyz.playedu.api.service.UserUploadImageLogService;
import xyz.playedu.api.mapper.UserUploadImageLogMapper;
import org.springframework.stereotype.Service;
/**
* @author tengteng
* @description 针对表user_upload_image_logs的数据库操作Service实现
* @createDate 2023-03-24 14:32:48
*/
@Service
public class UserUploadImageLogServiceImpl extends ServiceImpl<UserUploadImageLogMapper, UserUploadImageLog>
implements UserUploadImageLogService{
}

View File

@ -0,0 +1,18 @@
package xyz.playedu.api.types;
import lombok.Data;
/**
* @Author 杭州白书科技有限公司
* @create 2023/3/24 14:35
*/
@Data
public class UploadFileInfo {
private String originalName;
private String extension;
private long size;
private String saveName;
private String resourceType;
private String savePath;
private String url;
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.playedu.api.mapper.UserUploadImageLogMapper">
<resultMap id="BaseResultMap" type="xyz.playedu.api.domain.UserUploadImageLog">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="userId" column="user_id" jdbcType="INTEGER"/>
<result property="typed" column="typed" jdbcType="VARCHAR"/>
<result property="scene" column="scene" jdbcType="VARCHAR"/>
<result property="driver" column="driver" jdbcType="VARCHAR"/>
<result property="path" column="path" jdbcType="VARCHAR"/>
<result property="url" column="url" jdbcType="VARCHAR"/>
<result property="size" column="size" jdbcType="BIGINT"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="createdAt" column="created_at" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,user_id,typed,
scene,driver,path,
url,size,name,
created_at
</sql>
</mapper>