기존 GeoServerRegistrationService를 재사용하여 shapefile을 GeoServer에 등록 * + *
자동 선택 로직: - 파일 크기 < 100MB: REST API 업로드 (uploadShapefileZip) - 파일 크기 >= 100MB: 파일 경로 참조 + * (registerShapefileByPath) + * *
Conditional execution: geoserver.enabled=false 이면 skip
*/
@Component
@@ -24,6 +28,8 @@ public class GeoServerRegistrationTasklet implements Tasklet {
private static final Logger log = LoggerFactory.getLogger(GeoServerRegistrationTasklet.class);
+ private static final long FILE_SIZE_THRESHOLD = 100 * 1024 * 1024; // 100MB
+
private final GeoServerRegistrationService geoServerService;
@Value("#{jobParameters['geoserver.enabled'] ?: false}")
@@ -62,8 +68,29 @@ public class GeoServerRegistrationTasklet implements Tasklet {
throw new IllegalStateException("ZIP file path not available for GeoServer registration");
}
- // 기존 GeoServerRegistrationService 재사용
- geoServerService.uploadShapefileZip(zipPath, layerName);
+ // Check file size to determine registration method
+ File zipFile = new File(zipPath);
+ long fileSize = zipFile.length();
+ long fileSizeMB = fileSize / 1024 / 1024;
+
+ log.info("ZIP file size: {} bytes ({} MB)", fileSize, fileSizeMB);
+//
+// if (fileSize < FILE_SIZE_THRESHOLD) {
+// // Small file: Use REST API upload
+// log.info("Using REST API upload method (file size < 100MB)");
+// geoServerService.uploadShapefileZip(zipPath, layerName);
+// } else {
+// // Large file: Use file path reference
+// log.info(
+// "Using file path reference method (file size >= 100MB, {} MB recommended for large"
+// + " files)",
+// fileSizeMB);
+// log.info(
+// "GeoServer will read the file from: {} (ensure GeoServer has file system access)",
+// zipPath);
+// geoServerService.registerShapefileByPath(zipPath, layerName);
+// }
+ geoServerService.registerShapefileByPath(zipPath, layerName);
log.info("GeoServer registration completed successfully for layer: {}", layerName);
diff --git a/shp-exporter/src/main/java/com/kamco/makesample/cli/ConverterCommandLineRunner.java b/shp-exporter/src/main/java/com/kamco/makesample/cli/ConverterCommandLineRunner.java
index 8cfa7b4..4542d78 100755
--- a/shp-exporter/src/main/java/com/kamco/makesample/cli/ConverterCommandLineRunner.java
+++ b/shp-exporter/src/main/java/com/kamco/makesample/cli/ConverterCommandLineRunner.java
@@ -190,35 +190,56 @@ public class ConverterCommandLineRunner implements CommandLineRunner {
return;
}
- String filePath = firstOption(appArgs, "upload-shp");
- String layerName = firstOption(appArgs, "layer");
+ // Check for file path reference method (recommended for large files)
+ String filePathReference = firstOption(appArgs, "register-by-path");
+ boolean usePathReference = filePathReference != null && !filePathReference.isBlank();
- if (filePath == null || filePath.isBlank()) {
- log.info("No upload requested. Use --upload-shp option to upload a shapefile.");
+ // Check for upload method (traditional, file size limited)
+ String uploadFilePath = firstOption(appArgs, "upload-shp");
+ boolean useUpload = uploadFilePath != null && !uploadFilePath.isBlank();
+
+ if (!usePathReference && !useUpload) {
+ log.info("No upload or registration requested.");
printUsage();
return;
}
+ if (usePathReference && useUpload) {
+ log.error("Cannot use both --upload-shp and --register-by-path at the same time.");
+ log.error("Choose one method:");
+ log.error(" --upload-shp: Upload file content via REST API (< 100MB)");
+ log.error(" --register-by-path: Reference file path (500MB+)");
+ System.exit(1);
+ }
+
+ String filePath = usePathReference ? filePathReference : uploadFilePath;
+ String layerName = firstOption(appArgs, "layer");
+
if (layerName == null || layerName.isBlank()) {
String fileName = Paths.get(filePath).getFileName().toString();
layerName = fileName.replaceAll("(?i)\\.(zip|shp)$", ""); // 대소문자도 처리
}
log.info("========================================");
- log.info("Shapefile Upload to GeoServer");
+ log.info("Shapefile {} to GeoServer", usePathReference ? "Registration" : "Upload");
log.info("========================================");
+ log.info("Method: {}", usePathReference ? "File Path Reference" : "REST API Upload");
log.info("Input File: {}", filePath);
log.info("Layer Name: {}", layerName);
log.info("========================================");
try {
- geoServerService.uploadShapefileZip(filePath, layerName);
+ if (usePathReference) {
+ geoServerService.registerShapefileByPath(filePath, layerName);
+ } else {
+ geoServerService.uploadShapefileZip(filePath, layerName);
+ }
log.info("========================================");
- log.info("Upload completed successfully!");
+ log.info("{} completed successfully!", usePathReference ? "Registration" : "Upload");
log.info("========================================");
} catch (Exception e) {
log.error("========================================");
- log.error("Upload failed: {}", e.getMessage(), e);
+ log.error("{} failed: {}", usePathReference ? "Registration" : "Upload", e.getMessage(), e);
log.error("========================================");
throw e;
}
@@ -263,21 +284,44 @@ public class ConverterCommandLineRunner implements CommandLineRunner {
System.out.println();
System.out.println("Options:");
System.out.println(
- " --upload-shp LIMITATION: File size limited by HTTP request size (typically < 100MB) Use
+ * registerShapefileByPath() for larger files (500MB+)
+ *
+ * @param filePath Path to shapefile (.shp or .zip)
+ * @param layerName GeoServer layer name
+ */
public void uploadShapefileZip(String filePath, String layerName) {
String zipFilePath = filePath;
boolean tempZipCreated = false;
try {
- log.info("Starting shapefile upload to GeoServer");
+ log.info("Starting shapefile upload to GeoServer (REST API upload)");
log.info("Input file: {}", filePath);
log.info("Layer name: {}", layerName);
log.info("Workspace: {}", properties.getWorkspace());
@@ -59,6 +68,18 @@ public class GeoServerRegistrationService {
log.info("Temporary ZIP created: {}", zipFilePath);
}
+ // Check file size and warn if too large
+ Path path = Paths.get(zipFilePath);
+ long fileSize = Files.size(path);
+ log.info("ZIP file size: {} bytes ({} MB)", fileSize, fileSize / 1024 / 1024);
+
+ if (fileSize > 100 * 1024 * 1024) { // 100MB
+ log.warn(
+ "WARNING: File size ({} MB) may exceed HTTP upload limits. Consider using"
+ + " registerShapefileByPath() for files > 100MB",
+ fileSize / 1024 / 1024);
+ }
+
// Check if layer exists and handle overwrite
if (properties.isOverwriteExisting() && layerExists(layerName)) {
log.info("Layer '{}' already exists. Deleting...", layerName);
@@ -66,9 +87,7 @@ public class GeoServerRegistrationService {
}
// Read ZIP file
- Path path = Paths.get(zipFilePath);
byte[] zipData = Files.readAllBytes(path);
- log.info("ZIP file size: {} bytes", zipData.length);
// Upload to GeoServer
String url =
@@ -102,6 +121,24 @@ public class GeoServerRegistrationService {
"GeoServer upload failed. Status: {}, Response: {}",
e.getStatusCode(),
e.getResponseBodyAsString());
+
+ // Provide helpful message for 413 Payload Too Large
+ if (e.getStatusCode() == HttpStatus.PAYLOAD_TOO_LARGE) {
+ log.error("");
+ log.error("========================================");
+ log.error("ERROR: File size exceeds GeoServer upload limit (HTTP 413)");
+ log.error("");
+ log.error("Solution: Use file path reference method instead:");
+ log.error(" 1. Copy shapefile to GeoServer data directory");
+ log.error(" 2. Use registerShapefileByPath() method");
+ log.error("");
+ log.error("Or increase GeoServer upload limits:");
+ log.error(" - Tomcat: maxPostSize in server.xml");
+ log.error(" - Nginx: client_max_body_size");
+ log.error("========================================");
+ log.error("");
+ }
+
throw new RuntimeException("GeoServer upload failed", e);
} catch (Exception e) {
log.error("Unexpected error during shapefile upload", e);
@@ -119,6 +156,118 @@ public class GeoServerRegistrationService {
}
}
+ /**
+ * Register shapefile to GeoServer using file:// URL (for large files 500MB+)
+ *
+ * This method does NOT upload file content. Instead, it tells GeoServer to read the file from
+ * its local file system.
+ *
+ * Requirements: - GeoServer must have file system access to the shapefile path - The path must
+ * be absolute and accessible from GeoServer server
+ *
+ * @param absoluteFilePath Absolute file path to shapefile (.shp or .zip) on GeoServer server
+ * @param layerName GeoServer layer name
+ */
+ public void registerShapefileByPath(String absoluteFilePath, String layerName) {
+ try {
+ log.info("Starting shapefile registration to GeoServer (file path reference)");
+ log.info("Input file path: {}", absoluteFilePath);
+ log.info("Layer name: {}", layerName);
+ log.info("Workspace: {}", properties.getWorkspace());
+
+ // Validate inputs
+ if (absoluteFilePath == null || absoluteFilePath.trim().isEmpty()) {
+ throw new IllegalArgumentException("File path cannot be empty");
+ }
+
+ if (layerName == null || layerName.trim().isEmpty()) {
+ throw new IllegalArgumentException("Layer name cannot be empty");
+ }
+
+ // Verify file exists
+ File file = new File(absoluteFilePath);
+ if (!file.exists()) {
+ throw new IllegalArgumentException("File does not exist: " + absoluteFilePath);
+ }
+
+ if (!file.isAbsolute()) {
+ throw new IllegalArgumentException("File path must be absolute: " + absoluteFilePath);
+ }
+
+ String lowerPath = absoluteFilePath.toLowerCase();
+ if (!lowerPath.endsWith(".zip") && !lowerPath.endsWith(".shp")) {
+ throw new IllegalArgumentException("File must be a .zip or .shp file: " + absoluteFilePath);
+ }
+
+ log.info("File size: {} MB", file.length() / 1024 / 1024);
+
+ // Check if layer exists and handle overwrite
+ if (properties.isOverwriteExisting() && layerExists(layerName)) {
+ log.info("Layer '{}' already exists. Deleting...", layerName);
+ deleteLayer(layerName);
+ }
+
+ // Construct file:// URL
+ String fileUrl = "file://" + absoluteFilePath;
+ log.info("Using file URL: {}", fileUrl);
+
+ // GeoServer REST API endpoint
+ String url =
+ String.format(
+ "%s/rest/workspaces/%s/datastores/%s/file.shp?configure=all",
+ properties.getBaseUrl(), properties.getWorkspace(), layerName);
+
+ HttpHeaders headers = createHeaders();
+ headers.setContentType(MediaType.TEXT_PLAIN);
+
+ // Send file:// URL as request body
+ HttpEntity