diff --git a/han-note-oss/han-note-oss-api/pom.xml b/han-note-oss/han-note-oss-api/pom.xml
index d162cf2..1e2548a 100644
--- a/han-note-oss/han-note-oss-api/pom.xml
+++ b/han-note-oss/han-note-oss-api/pom.xml
@@ -20,5 +20,24 @@
com.hanserwei
hanserwei-common
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+
+
+
+ io.github.openfeign.form
+ feign-form-spring
+
+
+ io.github.openfeign.form
+ feign-form
+
diff --git a/han-note-oss/han-note-oss-api/src/main/java/com/hanserwei/hannote/oss/api/FileFeignApi.java b/han-note-oss/han-note-oss-api/src/main/java/com/hanserwei/hannote/oss/api/FileFeignApi.java
new file mode 100644
index 0000000..c5a656c
--- /dev/null
+++ b/han-note-oss/han-note-oss-api/src/main/java/com/hanserwei/hannote/oss/api/FileFeignApi.java
@@ -0,0 +1,26 @@
+package com.hanserwei.hannote.oss.api;
+
+import com.hanserwei.framework.common.response.Response;
+import com.hanserwei.hannote.oss.config.FeignFormConfig;
+import com.hanserwei.hannote.oss.constant.ApiConstants;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.multipart.MultipartFile;
+
+@FeignClient(name = ApiConstants.SERVICE_NAME, configuration = FeignFormConfig.class)
+public interface FileFeignApi {
+
+ String PREFIX = "/file";
+
+ /**
+ * 文件上传
+ *
+ * @param file 文件
+ * @return 文件上传结果
+ */
+ @PostMapping(value = PREFIX + "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ Response> uploadFile(@RequestPart(value = "file") MultipartFile file);
+
+}
\ No newline at end of file
diff --git a/han-note-oss/han-note-oss-api/src/main/java/com/hanserwei/hannote/oss/config/FeignFormConfig.java b/han-note-oss/han-note-oss-api/src/main/java/com/hanserwei/hannote/oss/config/FeignFormConfig.java
new file mode 100644
index 0000000..4ba89fb
--- /dev/null
+++ b/han-note-oss/han-note-oss-api/src/main/java/com/hanserwei/hannote/oss/config/FeignFormConfig.java
@@ -0,0 +1,16 @@
+package com.hanserwei.hannote.oss.config;
+
+import feign.codec.Encoder;
+import feign.form.spring.SpringFormEncoder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+@Configuration
+public class FeignFormConfig {
+
+ @Bean
+ public Encoder feignFormEncoder() {
+ return new SpringFormEncoder();
+ }
+}
\ No newline at end of file
diff --git a/han-note-oss/han-note-oss-api/src/main/java/com/hanserwei/hannote/oss/constant/ApiConstants.java b/han-note-oss/han-note-oss-api/src/main/java/com/hanserwei/hannote/oss/constant/ApiConstants.java
new file mode 100644
index 0000000..559f39e
--- /dev/null
+++ b/han-note-oss/han-note-oss-api/src/main/java/com/hanserwei/hannote/oss/constant/ApiConstants.java
@@ -0,0 +1,9 @@
+package com.hanserwei.hannote.oss.constant;
+
+public interface ApiConstants {
+
+ /**
+ * 服务名称
+ */
+ String SERVICE_NAME = "han-note-oss";
+}
\ No newline at end of file
diff --git a/han-note-oss/han-note-oss-biz/pom.xml b/han-note-oss/han-note-oss-biz/pom.xml
index 8d011fd..a4bf379 100644
--- a/han-note-oss/han-note-oss-biz/pom.xml
+++ b/han-note-oss/han-note-oss-biz/pom.xml
@@ -75,6 +75,23 @@
com.qcloud
cos_api
+
+ com.hanserwei
+ hanserwei-spring-boot-starter-biz-operationlog
+
+
+ com.hanserwei
+ hanserwei-spring-boot-starter-jackson
+
+
+ com.hanserwei
+ han-note-oss-api
+
+
+ com.hanserwei
+ hanserwei-spring-boot-starter-biz-context
+
+
diff --git a/han-note-oss/han-note-oss-biz/src/main/java/com/hanserwei/hannote/oss/controller/FileController.java b/han-note-oss/han-note-oss-biz/src/main/java/com/hanserwei/hannote/oss/controller/FileController.java
index 54748cb..fb6a04d 100644
--- a/han-note-oss/han-note-oss-biz/src/main/java/com/hanserwei/hannote/oss/controller/FileController.java
+++ b/han-note-oss/han-note-oss-biz/src/main/java/com/hanserwei/hannote/oss/controller/FileController.java
@@ -1,5 +1,6 @@
package com.hanserwei.hannote.oss.controller;
+import com.hanserwei.framework.biz.context.holder.LoginUserContextHolder;
import com.hanserwei.framework.common.response.Response;
import com.hanserwei.hannote.oss.service.FileService;
import jakarta.annotation.Resource;
@@ -21,6 +22,7 @@ public class FileController {
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Response> uploadFile(@RequestPart(value = "file") MultipartFile file) {
+ log.info("当前用户 ID: {}", LoginUserContextHolder.getUserId());
return fileService.uploadFile(file);
}
diff --git a/han-note-oss/han-note-oss-biz/src/main/resources/application.yml b/han-note-oss/han-note-oss-biz/src/main/resources/application.yml
index a814e02..eb46fe6 100644
--- a/han-note-oss/han-note-oss-biz/src/main/resources/application.yml
+++ b/han-note-oss/han-note-oss-biz/src/main/resources/application.yml
@@ -4,6 +4,10 @@ server:
spring:
profiles:
active: dev # 默认激活 dev 本地开发环境
+ servlet:
+ multipart:
+ max-file-size: 20MB # 单个文件最大大小
+ max-request-size: 100MB # 单次请求最大大小(包含多个文件)
storage:
type: rustfs # 对象存储类型
\ No newline at end of file
diff --git a/han-note-user/han-note-user-biz/pom.xml b/han-note-user/han-note-user-biz/pom.xml
index 3474506..34c572e 100644
--- a/han-note-user/han-note-user-biz/pom.xml
+++ b/han-note-user/han-note-user-biz/pom.xml
@@ -66,6 +66,10 @@
com.hanserwei
hanserwei-spring-boot-starter-biz-context
+
+ com.hanserwei
+ han-note-oss-api
+
diff --git a/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/HannoteUserBizApplication.java b/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/HannoteUserBizApplication.java
index 21ad5df..dc1639c 100644
--- a/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/HannoteUserBizApplication.java
+++ b/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/HannoteUserBizApplication.java
@@ -3,9 +3,11 @@ package com.hanserwei.hannote.user.biz;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@MapperScan("com.hanserwei.hannote.user.biz.domain.mapper")
+@EnableFeignClients(basePackages = "com.hanserwei.hannote")
public class HannoteUserBizApplication {
public static void main(String[] args) {
SpringApplication.run(HannoteUserBizApplication.class, args);
diff --git a/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/enums/ResponseCodeEnum.java b/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/enums/ResponseCodeEnum.java
index 1a61efe..97c1f0f 100644
--- a/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/enums/ResponseCodeEnum.java
+++ b/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/enums/ResponseCodeEnum.java
@@ -17,7 +17,8 @@ public enum ResponseCodeEnum implements BaseExceptionInterface {
HAN_NOTE_ID_VALID_FAIL("USER-20002", "小憨书号请设置6-15个字符,仅可使用英文(必须)、数字、下划线"),
SEX_VALID_FAIL("USER-20003", "性别错误"),
INTRODUCTION_VALID_FAIL("USER-20004", "个人简介请设置1-100个字符"),
- ;
+ UPLOAD_AVATAR_FAIL("USER-20005", "头像上传失败"),
+ UPLOAD_BACKGROUND_IMG_FAIL("USER-20006", "背景图上传失败"),
;
// 异常码
diff --git a/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/rpc/OssRpcService.java b/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/rpc/OssRpcService.java
new file mode 100644
index 0000000..0bd7c4c
--- /dev/null
+++ b/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/rpc/OssRpcService.java
@@ -0,0 +1,26 @@
+package com.hanserwei.hannote.user.biz.rpc;
+
+import com.hanserwei.framework.common.response.Response;
+import com.hanserwei.hannote.oss.api.FileFeignApi;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+@Component
+public class OssRpcService {
+
+ @Resource
+ private FileFeignApi fileFeignApi;
+
+ public String uploadFile(MultipartFile file) {
+ // 调用对象存储服务上传文件
+ Response> response = fileFeignApi.uploadFile(file);
+
+ if (!response.isSuccess()) {
+ return null;
+ }
+
+ // 返回图片访问链接
+ return (String) response.getData();
+ }
+}
\ No newline at end of file
diff --git a/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/service/impl/UserServiceImpl.java b/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/service/impl/UserServiceImpl.java
index 2052cf3..4544921 100644
--- a/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/service/impl/UserServiceImpl.java
+++ b/han-note-user/han-note-user-biz/src/main/java/com/hanserwei/hannote/user/biz/service/impl/UserServiceImpl.java
@@ -3,6 +3,7 @@ package com.hanserwei.hannote.user.biz.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Preconditions;
import com.hanserwei.framework.biz.context.holder.LoginUserContextHolder;
+import com.hanserwei.framework.common.exception.ApiException;
import com.hanserwei.framework.common.response.Response;
import com.hanserwei.framework.common.utils.ParamUtils;
import com.hanserwei.hannote.user.biz.domain.dataobject.UserDO;
@@ -10,7 +11,9 @@ import com.hanserwei.hannote.user.biz.domain.mapper.UserDOMapper;
import com.hanserwei.hannote.user.biz.enums.ResponseCodeEnum;
import com.hanserwei.hannote.user.biz.enums.SexEnum;
import com.hanserwei.hannote.user.biz.model.vo.UpdateUserInfoReqVO;
+import com.hanserwei.hannote.user.biz.rpc.OssRpcService;
import com.hanserwei.hannote.user.biz.service.UserService;
+import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
@@ -23,6 +26,10 @@ import java.util.Objects;
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl implements UserService {
+
+ @Resource
+ private OssRpcService ossRpcService;
+
@Override
public Response> updateUserInfo(UpdateUserInfoReqVO updateUserInfoReqVO) {
UserDO userDO = new UserDO();
@@ -35,7 +42,16 @@ public class UserServiceImpl extends ServiceImpl implement
MultipartFile avatar = updateUserInfoReqVO.getAvatar();
if (Objects.nonNull(avatar)) {
- // TODO: 上传头像,调用服务
+ String avatarUrl = ossRpcService.uploadFile(avatar);
+ log.info("==> 调用 oss 服务成功,上传头像,url:{}", avatarUrl);
+
+ // 若上传头像失败,则抛出业务异常
+ if (StringUtils.isBlank(avatarUrl)) {
+ throw new ApiException(ResponseCodeEnum.UPLOAD_AVATAR_FAIL);
+ }
+
+ userDO.setAvatar(avatarUrl);
+ needUpdate = true;
}
// 昵称
@@ -80,7 +96,16 @@ public class UserServiceImpl extends ServiceImpl implement
// 背景图片
MultipartFile backgroundImg = updateUserInfoReqVO.getBackgroundImg();
if (Objects.nonNull(backgroundImg)) {
- // TODO: 上传背景图片,调用服务
+ String backgroundImgUrl = ossRpcService.uploadFile(backgroundImg);
+ log.info("==> 调用 oss 服务成功,上传背景图,url:{}", backgroundImg);
+
+ // 若上传背景图失败,则抛出业务异常
+ if (StringUtils.isBlank(backgroundImgUrl)) {
+ throw new ApiException(ResponseCodeEnum.UPLOAD_BACKGROUND_IMG_FAIL);
+ }
+
+ userDO.setBackgroundImg(backgroundImgUrl);
+ needUpdate = true;
}
if (needUpdate) {
diff --git a/han-note-user/han-note-user-biz/src/main/resources/application.yml b/han-note-user/han-note-user-biz/src/main/resources/application.yml
index d30dcbc..e532ea4 100644
--- a/han-note-user/han-note-user-biz/src/main/resources/application.yml
+++ b/han-note-user/han-note-user-biz/src/main/resources/application.yml
@@ -4,6 +4,10 @@ server:
spring:
profiles:
active: dev # 默认激活 dev 本地开发环境
+ servlet:
+ multipart:
+ max-file-size: 20MB # 单个文件最大大小
+ max-request-size: 100MB # 单次请求最大大小(包含多个文件)
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/pom.xml b/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/pom.xml
index 6f4ca31..93bb8b5 100644
--- a/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/pom.xml
+++ b/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/pom.xml
@@ -43,6 +43,9 @@
com.alibaba
transmittable-thread-local
-
+
+ io.github.openfeign
+ feign-core
+
diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/src/main/java/com/hanserwei/framework/biz/context/config/FeignContextAutoConfiguration.java b/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/src/main/java/com/hanserwei/framework/biz/context/config/FeignContextAutoConfiguration.java
new file mode 100644
index 0000000..f6547e5
--- /dev/null
+++ b/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/src/main/java/com/hanserwei/framework/biz/context/config/FeignContextAutoConfiguration.java
@@ -0,0 +1,14 @@
+package com.hanserwei.framework.biz.context.config;
+
+import com.hanserwei.framework.biz.context.interceptor.FeignRequestInterceptor;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.Bean;
+
+@AutoConfiguration
+public class FeignContextAutoConfiguration {
+
+ @Bean
+ public FeignRequestInterceptor feignRequestInterceptor() {
+ return new FeignRequestInterceptor();
+ }
+}
\ No newline at end of file
diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/src/main/java/com/hanserwei/framework/biz/context/interceptor/FeignRequestInterceptor.java b/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/src/main/java/com/hanserwei/framework/biz/context/interceptor/FeignRequestInterceptor.java
new file mode 100644
index 0000000..fae8810
--- /dev/null
+++ b/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/src/main/java/com/hanserwei/framework/biz/context/interceptor/FeignRequestInterceptor.java
@@ -0,0 +1,25 @@
+package com.hanserwei.framework.biz.context.interceptor;
+
+import com.hanserwei.framework.biz.context.holder.LoginUserContextHolder;
+import com.hanserwei.framework.common.constant.GlobalConstants;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Objects;
+
+@Slf4j
+public class FeignRequestInterceptor implements RequestInterceptor {
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {
+ // 获取当前上下文中的用户 ID
+ Long userId = LoginUserContextHolder.getUserId();
+
+ // 若不为空,则添加到请求头中
+ if (Objects.nonNull(userId)) {
+ requestTemplate.header(GlobalConstants.USER_ID, String.valueOf(userId));
+ log.info("########## feign 请求设置请求头 userId: {}", userId);
+ }
+ }
+}
\ No newline at end of file
diff --git a/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index d6d4fbb..98d7e67 100644
--- a/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/hanserwei-framework/hanserwei-spring-boot-starter-biz-context/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1 +1,2 @@
-com.hanserwei.framework.biz.context.config.ContextAutoConfiguration
\ No newline at end of file
+com.hanserwei.framework.biz.context.config.ContextAutoConfiguration
+com.hanserwei.framework.biz.context.config.FeignContextAutoConfiguration
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index f65c49e..616dc0f 100755
--- a/pom.xml
+++ b/pom.xml
@@ -50,6 +50,7 @@
1.1.1
2.3.3
5.6.227
+ 3.8.0
@@ -203,6 +204,17 @@
cos_api
${cos-api.version}
+
+ com.hanserwei
+ han-note-oss-api
+ ${revision}
+
+
+
+ io.github.openfeign.form
+ feign-form
+ ${feign-form.version}
+