import geopandas as gpd import fiona import zipfile import tempfile import os import shutil def read_gdb(zip_path: str, layer: str = None): if not zip_path.lower().endswith(".zip"): raise ValueError("File GDB harus berupa ZIP yang berisi folder .gdb atau file .gdbtable") tmpdir = tempfile.mkdtemp() with zipfile.ZipFile(zip_path, "r") as zip_ref: zip_ref.extractall(tmpdir) macosx_path = os.path.join(tmpdir, "__MACOSX") if os.path.exists(macosx_path): shutil.rmtree(macosx_path) gdb_folders = [] for root, dirs, _ in os.walk(tmpdir): for d in dirs: if d.lower().endswith(".gdb"): gdb_folders.append(os.path.join(root, d)) if not gdb_folders: gdbtable_files = [] for root, _, files in os.walk(tmpdir): for f in files: if f.lower().endswith(".gdbtable"): gdbtable_files.append(os.path.join(root, f)) if gdbtable_files: first_folder = os.path.dirname(gdbtable_files[0]) base_name = os.path.basename(first_folder) gdb_folder_path = os.path.join(tmpdir, f"{base_name}.gdb") os.makedirs(gdb_folder_path, exist_ok=True) for fpath in os.listdir(first_folder): if ".gdb" in fpath.lower(): shutil.move(os.path.join(first_folder, fpath), os.path.join(gdb_folder_path, fpath)) gdb_folders.append(gdb_folder_path) # print(f"[INFO] Rebuilt GDB folder from nested structure: {gdb_folder_path}") else: # print("[DEBUG] Isi ZIP:", os.listdir(tmpdir)) shutil.rmtree(tmpdir) raise ValueError("Tidak ditemukan folder .gdb atau file .gdbtable di dalam ZIP") gdb_path = gdb_folders[0] layers = fiona.listlayers(gdb_path) # print(f"[INFO] Layer tersedia: {layers}") chosen_layer = layer or (layers[0] if layers else None) if not chosen_layer: shutil.rmtree(tmpdir) raise ValueError("Tidak ada layer GDB yang bisa dibaca.") print(f"[DEBUG] Membaca layer: {chosen_layer}") try: gdf = gpd.read_file(gdb_path, layer=chosen_layer) except Exception as e: shutil.rmtree(tmpdir) raise ValueError(f"Gagal membaca layer dari GDB: {e}") if gdf.crs is None: # print("[WARN] CRS tidak terdeteksi, diasumsikan EPSG:4326") gdf.set_crs("EPSG:4326", inplace=True) shutil.rmtree(tmpdir) return gdf