shp파일등록방법변경
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.kamco.makesample.batch.tasklet;
|
||||
|
||||
import com.kamco.makesample.service.GeoServerRegistrationService;
|
||||
import java.io.File;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
@@ -16,6 +17,9 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
* <p>기존 GeoServerRegistrationService를 재사용하여 shapefile을 GeoServer에 등록
|
||||
*
|
||||
* <p>자동 선택 로직: - 파일 크기 < 100MB: REST API 업로드 (uploadShapefileZip) - 파일 크기 >= 100MB: 파일 경로 참조
|
||||
* (registerShapefileByPath)
|
||||
*
|
||||
* <p>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);
|
||||
|
||||
|
||||
@@ -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 <file-path> Upload shapefile to GeoServer (.shp or .zip)");
|
||||
" --upload-shp <file-path> Upload shapefile via REST API (< 100MB)");
|
||||
System.out.println(
|
||||
" --layer <layer-name> Specify layer name (optional, defaults to filename)");
|
||||
System.out.println(" --help, -h Show this help message");
|
||||
" --register-by-path <file-path> Register shapefile using file path (500MB+)");
|
||||
System.out.println(
|
||||
" --layer <layer-name> Specify layer name (optional, defaults to filename)");
|
||||
System.out.println(" --help, -h Show this help message");
|
||||
System.out.println();
|
||||
System.out.println("GeoServer Registration Methods:");
|
||||
System.out.println();
|
||||
System.out.println(" 1. REST API Upload (--upload-shp):");
|
||||
System.out.println(" - Uploads file content to GeoServer via HTTP");
|
||||
System.out.println(" - File size limit: < 100MB (HTTP payload limit)");
|
||||
System.out.println(" - Use for small to medium files");
|
||||
System.out.println();
|
||||
System.out.println(" 2. File Path Reference (--register-by-path):");
|
||||
System.out.println(" - GeoServer reads file from its local file system");
|
||||
System.out.println(" - No file size limit (supports 500MB ~ 2GB+)");
|
||||
System.out.println(" - Requirements:");
|
||||
System.out.println(" * GeoServer must have file system access to the path");
|
||||
System.out.println(" * Path must be absolute (e.g., /data/model_output/...)");
|
||||
System.out.println(" * File must be readable by GeoServer user");
|
||||
System.out.println();
|
||||
System.out.println("Examples:");
|
||||
System.out.println(" # Upload ZIP file directly");
|
||||
System.out.println(" java -jar shp-exporter.jar --upload-shp /path/to/shapefile.zip");
|
||||
System.out.println();
|
||||
System.out.println(" # Upload .shp file (will auto-create ZIP with related files)");
|
||||
System.out.println(" java -jar shp-exporter.jar --upload-shp /path/to/shapefile.shp");
|
||||
System.out.println(" # Small file (< 100MB): Upload via REST API");
|
||||
System.out.println(" java -jar shp-exporter.jar --upload-shp /path/to/small_file.zip");
|
||||
System.out.println();
|
||||
System.out.println(" # Specify custom layer name");
|
||||
System.out.println(" # Large file (500MB+): Register by file path");
|
||||
System.out.println(
|
||||
" java -jar shp-exporter.jar --upload-shp /path/to/shapefile.shp --layer my_layer");
|
||||
" java -jar shp-exporter.jar --register-by-path"
|
||||
+ " /data/model_output/export/inference_id/merge/large_file.zip");
|
||||
System.out.println();
|
||||
System.out.println(" # With custom layer name");
|
||||
System.out.println(
|
||||
" java -jar shp-exporter.jar --register-by-path /path/to/file.zip --layer my_layer");
|
||||
System.out.println();
|
||||
System.out.println(" # Auto-create ZIP from .shp file (upload method)");
|
||||
System.out.println(" java -jar shp-exporter.jar --upload-shp /path/to/shapefile.shp");
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,12 +38,21 @@ public class GeoServerRegistrationService {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register shapefile to GeoServer by uploading file content (REST API)
|
||||
*
|
||||
* <p>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+)
|
||||
*
|
||||
* <p>This method does NOT upload file content. Instead, it tells GeoServer to read the file from
|
||||
* its local file system.
|
||||
*
|
||||
* <p>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<String> request = new HttpEntity<>(fileUrl, headers);
|
||||
|
||||
log.info("Registering shapefile to GeoServer: {}", url);
|
||||
ResponseEntity<String> response =
|
||||
restTemplate.exchange(url, HttpMethod.PUT, request, String.class);
|
||||
|
||||
if (response.getStatusCode() == HttpStatus.CREATED
|
||||
|| response.getStatusCode() == HttpStatus.OK) {
|
||||
log.info("Shapefile registered successfully to GeoServer");
|
||||
log.info(
|
||||
"Layer '{}' is now available in workspace '{}'", layerName, properties.getWorkspace());
|
||||
log.info("GeoServer will read data from: {}", absoluteFilePath);
|
||||
} else {
|
||||
log.warn("Unexpected response status: {}", response.getStatusCode());
|
||||
}
|
||||
|
||||
} catch (HttpClientErrorException e) {
|
||||
log.error(
|
||||
"GeoServer registration failed. Status: {}, Response: {}",
|
||||
e.getStatusCode(),
|
||||
e.getResponseBodyAsString());
|
||||
|
||||
if (e.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR) {
|
||||
log.error("");
|
||||
log.error("========================================");
|
||||
log.error("ERROR: GeoServer cannot access the file path");
|
||||
log.error("");
|
||||
log.error("Possible causes:");
|
||||
log.error(" 1. File path is not accessible from GeoServer server");
|
||||
log.error(" 2. GeoServer user lacks read permissions");
|
||||
log.error(" 3. File path format is incorrect (must be absolute path)");
|
||||
log.error("");
|
||||
log.error("Solutions:");
|
||||
log.error(" 1. Verify GeoServer has file system access to: {}", absoluteFilePath);
|
||||
log.error(" 2. Check file permissions (chmod 644 or similar)");
|
||||
log.error(" 3. Ensure path is absolute and correctly formatted");
|
||||
log.error("========================================");
|
||||
log.error("");
|
||||
}
|
||||
|
||||
throw new RuntimeException("GeoServer registration failed", e);
|
||||
} catch (Exception e) {
|
||||
log.error("Unexpected error during shapefile registration", e);
|
||||
throw new RuntimeException("Shapefile registration failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateInputs(String filePath, String layerName) {
|
||||
if (filePath == null || filePath.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("File path cannot be empty");
|
||||
|
||||
Reference in New Issue
Block a user