diff --git a/reading-platform-java/Dockerfile b/reading-platform-java/Dockerfile
new file mode 100644
index 0000000..103005d
--- /dev/null
+++ b/reading-platform-java/Dockerfile
@@ -0,0 +1,13 @@
+FROM maven:3.9-eclipse-temurin-21 AS build
+WORKDIR /app
+COPY pom.xml .
+RUN mvn dependency:go-offline -q
+COPY src ./src
+RUN mvn package -DskipTests -q
+
+FROM eclipse-temurin:21-jre-alpine
+WORKDIR /app
+COPY --from=build /app/target/*.jar app.jar
+RUN mkdir -p /app/uploads
+EXPOSE 8080
+ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=prod", "app.jar"]
diff --git a/reading-platform-java/pom.xml b/reading-platform-java/pom.xml
index ad46c3a..e6a7117 100644
--- a/reading-platform-java/pom.xml
+++ b/reading-platform-java/pom.xml
@@ -24,6 +24,8 @@
0.12.5
4.4.0
5.8.26
+ 5.2.5
+ 10.8.1
@@ -32,6 +34,10 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
org.springframework.boot
spring-boot-starter-validation
@@ -95,6 +101,25 @@
true
+
+
+ org.apache.poi
+ poi-ooxml
+ ${poi.version}
+
+
+
+
+ org.flywaydb
+ flyway-core
+ ${flyway.version}
+
+
+ org.flywaydb
+ flyway-mysql
+ ${flyway.version}
+
+
org.springframework.boot
diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/config/SecurityConfig.java b/reading-platform-java/src/main/java/com/reading/platform/common/config/SecurityConfig.java
index cabafca..e244ec7 100644
--- a/reading-platform-java/src/main/java/com/reading/platform/common/config/SecurityConfig.java
+++ b/reading-platform-java/src/main/java/com/reading/platform/common/config/SecurityConfig.java
@@ -40,11 +40,11 @@ public class SecurityConfig {
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
// Public endpoints
- .requestMatchers("/api/auth/**").permitAll()
+ .requestMatchers("/api/v1/auth/**").permitAll()
// Swagger/Knife4j endpoints
.requestMatchers("/doc.html", "/swagger-ui/**", "/v3/api-docs/**", "/webjars/**").permitAll()
- // Static resources
- .requestMatchers("/static/**", "/favicon.ico").permitAll()
+ // Static resources - uploads
+ .requestMatchers("/uploads/**", "/static/**", "/favicon.ico").permitAll()
// OPTIONS requests
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// All other requests require authentication
diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/config/WebMvcConfig.java b/reading-platform-java/src/main/java/com/reading/platform/common/config/WebMvcConfig.java
new file mode 100644
index 0000000..8659597
--- /dev/null
+++ b/reading-platform-java/src/main/java/com/reading/platform/common/config/WebMvcConfig.java
@@ -0,0 +1,19 @@
+package com.reading.platform.common.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+ @Value("${file.upload.path:/app/uploads/}")
+ private String uploadPath;
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ registry.addResourceHandler("/uploads/**")
+ .addResourceLocations("file:" + uploadPath);
+ }
+}
diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/response/Result.java b/reading-platform-java/src/main/java/com/reading/platform/common/response/Result.java
index d6f8110..07b7459 100644
--- a/reading-platform-java/src/main/java/com/reading/platform/common/response/Result.java
+++ b/reading-platform-java/src/main/java/com/reading/platform/common/response/Result.java
@@ -1,5 +1,6 @@
package com.reading.platform.common.response;
+import com.reading.platform.common.enums.ErrorCode;
import lombok.Data;
import java.io.Serializable;
@@ -47,4 +48,8 @@ public class Result implements Serializable {
return error(500, message);
}
+ public static Result error(ErrorCode errorCode) {
+ return error(errorCode.getCode(), errorCode.getMessage());
+ }
+
}
diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/FileUploadController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/FileUploadController.java
new file mode 100644
index 0000000..e57617c
--- /dev/null
+++ b/reading-platform-java/src/main/java/com/reading/platform/controller/FileUploadController.java
@@ -0,0 +1,38 @@
+package com.reading.platform.controller;
+
+import com.reading.platform.common.response.Result;
+import com.reading.platform.service.FileUploadService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Tag(name = "File Upload", description = "File Upload APIs")
+@RestController
+@RequestMapping("/api/v1/files")
+@RequiredArgsConstructor
+public class FileUploadController {
+
+ private final FileUploadService fileUploadService;
+
+ @Operation(summary = "Upload file")
+ @PostMapping("/upload")
+ public Result