Files
UAS_WebGIS_CeciliaYvonGunaw…/povertymap/api/upload.php
T
2026-06-10 22:12:35 +07:00

119 lines
3.9 KiB
PHP

<?php
require_once __DIR__ . '/config.php';
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
header('Access-Control-Allow-Credentials: true');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') exit;
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(['error' => 'Method tidak didukung'], 405);
}
$user = requireRole(['admin', 'surveyor']);
// ── Validasi file ────────────────────────────
if (!isset($_FILES['foto']) || $_FILES['foto']['error'] !== UPLOAD_ERR_OK) {
jsonResponse(['success' => false, 'error' => 'File foto wajib diunggah'], 422);
}
$file = $_FILES['foto'];
// Cek ukuran
if ($file['size'] > MAX_UPLOAD_SIZE) {
jsonResponse(['success' => false, 'error' => 'Ukuran file melebihi batas 5MB'], 422);
}
// Cek tipe file
$allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
if (!in_array($mimeType, $allowedTypes)) {
jsonResponse(['success' => false, 'error' => 'Hanya file JPEG dan PNG yang diizinkan'], 422);
}
// ── Buat folder uploads jika belum ada ───────
if (!is_dir(UPLOAD_DIR)) {
mkdir(UPLOAD_DIR, 0755, true);
}
// ── Generate nama file unik ──────────────────
$ext = ($mimeType === 'image/png') ? 'png' : 'jpg';
$filename = date('Ymd_His') . '_' . bin2hex(random_bytes(4)) . '.' . $ext;
$destPath = UPLOAD_DIR . $filename;
$webPath = 'uploads/' . $filename;
// ── Pindahkan file ───────────────────────────
if (!move_uploaded_file($file['tmp_name'], $destPath)) {
jsonResponse(['success' => false, 'error' => 'Gagal menyimpan file'], 500);
}
// ── Extract EXIF GPS ─────────────────────────
$lat = null;
$lng = null;
$hasGps = false;
if ($mimeType === 'image/jpeg' || $mimeType === 'image/jpg') {
$exif = @exif_read_data($destPath, 'GPS', true);
if ($exif && isset($exif['GPS']['GPSLatitude']) && isset($exif['GPS']['GPSLongitude'])) {
$lat = exifGpsToDecimal(
$exif['GPS']['GPSLatitude'],
$exif['GPS']['GPSLatitudeRef'] ?? 'N'
);
$lng = exifGpsToDecimal(
$exif['GPS']['GPSLongitude'],
$exif['GPS']['GPSLongitudeRef'] ?? 'E'
);
$hasGps = true;
}
}
auditLog(getDB(), $user['id'], 'UPLOAD_FOTO', null, null, null, [
'filename' => $filename, 'has_gps' => $hasGps
]);
jsonResponse([
'success' => true,
'foto_path' => $webPath,
'lat' => $lat,
'lng' => $lng,
'has_gps' => $hasGps,
]);
// ══════════════════════════════════════════════
// EXIF GPS Helper
// ══════════════════════════════════════════════
/**
* Konversi EXIF GPS coordinate (DMS) ke desimal
* @param array $coord Array of 3 fractions [degrees, minutes, seconds]
* @param string $ref Hemisphere reference (N/S/E/W)
*/
function exifGpsToDecimal(array $coord, string $ref): float {
$degrees = exifFractionToFloat($coord[0]);
$minutes = exifFractionToFloat($coord[1]);
$seconds = exifFractionToFloat($coord[2]);
$decimal = $degrees + ($minutes / 60) + ($seconds / 3600);
if ($ref === 'S' || $ref === 'W') {
$decimal *= -1;
}
return round($decimal, 8);
}
/**
* Konversi fraction string "num/den" ke float
*/
function exifFractionToFloat(string $fraction): float {
$parts = explode('/', $fraction);
if (count($parts) === 2 && (float)$parts[1] !== 0.0) {
return (float)$parts[0] / (float)$parts[1];
}
return (float)$parts[0];
}