COS对象存储实战——用户头像相关
官方SDK:https://cloud.tencent.com/document/product/436/10199
环境:
需要先开通COS对象存储服务:https://cloud.tencent.com/document/product/436
安装SDK
<dependency> <groupId>com.qcloud</groupId> <artifactId>cos_api</artifactId> <version>${latest.version}</version> </dependency>
|
配置COS对象存储
[application.yml]
cos: client: accessKey: XXX secretKey: xxx region: xxx bucket: xxx
|
[客户端配置]
@Data @Configuration @ConfigurationProperties(prefix = "cos.client") public class CosClientConfig {
private String accessKey;
private String secretKey;
private String region;
private String bucket;
@Bean public COSClient cosClient() { COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey); ClientConfig clientConfig = new ClientConfig(new Region(region)); return new COSClient(cred, clientConfig); } }
|
更多配置:https://cloud.tencent.com/document/product/436/10199#.E5.88.9D.E5.A7.8B.E5.8C.96.E5.AE.A2.E6.88.B7.E7.AB.AF
编写Manager
@Component public class CosManager {
@Resource private CosClientConfig cosClientConfig;
@Resource private COSClient cosClient;
public PutObjectResult putObject(String key, String localFilePath) { PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key,new File(localFilePath)); return cosClient.putObject(putObjectRequest); }
public PutObjectResult putObject(String key, File file) { PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key,file); return cosClient.putObject(putObjectRequest); } }
|
上传业务
=> 用户上传头像,返回可访问链接,保存至数据库
[FileConstant]
public interface FileConstant {
String COS_HOST = "自己配置好的COS访问地址前缀"; }
|
[FileController]
@Slf4j @RestController @RequestMapping("/file") public class FileController {
final long ONE_MB = 1024 * 1024L;
@Resource private UserService userService;
@Resource private CosManager cosManager;
@Resource private RedisTemplate<String, Object> redisTemplate; private static final List<String> VALID_AVATAR_SUFFIX_LIST = Arrays.asList("jpeg", "jpg", "svg", "png", "webp");
@PostMapping("/upload") public BaseResponse<String> uploadFile(@RequestPart("file") MultipartFile multipartFile, HttpServletRequest request) { validFile(multipartFile); User loginUser = userService.getLoginUser(request); String uuid = RandomStringUtils.randomAlphanumeric(8); String filename = uuid + "-" + multipartFile.getOriginalFilename(); String filepath = String.format("/user_avatar/%s/%s", loginUser.getId(), filename); File file = null; try { file = File.createTempFile(filepath, null); multipartFile.transferTo(file); cosManager.putObject(filepath, file); return ResultUtil.success(FileConstant.COS_HOST + filepath); } catch (Exception e) { log.error("file upload error, filepath = " + filepath, e); throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败"); } finally { if (file != null) { boolean delete = file.delete(); if (!delete) { log.error("file delete error, filepath = {}", filepath); } } } }
private void validFile(MultipartFile multipartFile) { long fileSize = multipartFile.getSize(); String fileSuffix = FileUtil.getSuffix(multipartFile.getOriginalFilename()); if (fileSize > ONE_MB) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件大小不能超过 1M"); } if (!VALID_AVATAR_SUFFIX_LIST.contains(fileSuffix)) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件类型错误"); } } }
|
[前端处理]
const res = await request.post("/file/upload", { 'file': fileFile, }, { headers: {'Content-Type': 'multipart/form-data'}, })
const updateUserAvatarUrl = await request.post("/user/update", { id: user.value.id, userAvatarUrl: res })
|
扩展: