Primer commit del sistema separado falta mejorar mucho
This commit is contained in:
237
gallery/api/upload.php
Executable file
237
gallery/api/upload.php
Executable file
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
/**
|
||||
* API de Galería - Subida de imágenes
|
||||
*/
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Cargar variables de entorno
|
||||
if (file_exists(__DIR__ . '/../../.env')) {
|
||||
$lines = file(__DIR__ . '/../../.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
foreach ($lines as $line) {
|
||||
if (strpos(trim($line), '#') === 0) continue;
|
||||
if (strpos($line, '=') === false) continue;
|
||||
list($key, $value) = explode('=', $line, 2);
|
||||
$_ENV[trim($key)] = trim($value);
|
||||
}
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../../shared/database/connection.php';
|
||||
require_once __DIR__ . '/../../shared/auth/jwt.php';
|
||||
|
||||
// Verificar autenticación
|
||||
$userData = JWTAuth::authenticate();
|
||||
if (!$userData) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['success' => false, 'error' => 'No autenticado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Permitir subida a cualquier usuario autenticado
|
||||
// Opcional: Restringir si es necesario
|
||||
// if (!hasPermission('editar_plantillas') && !hasPermission('crear_mensajes')) { ... }
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'error' => 'Método no permitido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($_FILES['image'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'No se envió ninguna imagen']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = $_FILES['image'];
|
||||
|
||||
// Validar errores de subida
|
||||
if ($file['error'] !== UPLOAD_ERR_OK) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'Error al subir el archivo']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Validar tipo de archivo
|
||||
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mimeType = finfo_file($finfo, $file['tmp_name']);
|
||||
finfo_close($finfo);
|
||||
|
||||
if (!in_array($mimeType, $allowedTypes)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'Tipo de archivo no permitido. Solo se aceptan JPG, PNG, GIF y WebP']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Validar tamaño (máximo 5MB)
|
||||
if ($file['size'] > 5 * 1024 * 1024) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'El archivo es muy grande. Máximo 5MB']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$db = getDB();
|
||||
|
||||
// Calcular hash MD5 del archivo
|
||||
$hash = md5_file($file['tmp_name']);
|
||||
|
||||
// Verificar si ya existe una imagen con el mismo hash
|
||||
$stmt = $db->prepare("SELECT * FROM gallery WHERE hash_md5 = ?");
|
||||
$stmt->execute([$hash]);
|
||||
$existing = $stmt->fetch();
|
||||
|
||||
if ($existing) {
|
||||
// La imagen ya existe, devolver la existente
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'duplicate' => true,
|
||||
'image' => [
|
||||
'id' => $existing['id'],
|
||||
'nombre' => $existing['nombre'],
|
||||
'ruta' => $existing['ruta'],
|
||||
'ruta_thumbnail' => $existing['ruta_thumbnail'],
|
||||
'url' => '/gallery/uploads/' . $existing['nombre'],
|
||||
'url_thumbnail' => '/gallery/thumbnails/' . $existing['nombre']
|
||||
]
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Obtener dimensiones de la imagen
|
||||
$imageInfo = getimagesize($file['tmp_name']);
|
||||
$width = $imageInfo[0];
|
||||
$height = $imageInfo[1];
|
||||
|
||||
// Generar nombre único para el archivo
|
||||
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||
$newName = time() . '_' . bin2hex(random_bytes(8)) . '.' . $extension;
|
||||
|
||||
// Rutas de destino
|
||||
$uploadsDir = __DIR__ . '/../uploads/';
|
||||
$thumbnailsDir = __DIR__ . '/../thumbnails/';
|
||||
$uploadPath = $uploadsDir . $newName;
|
||||
$thumbnailPath = $thumbnailsDir . $newName;
|
||||
|
||||
// Crear directorios si no existen
|
||||
if (!is_dir($uploadsDir)) {
|
||||
mkdir($uploadsDir, 0755, true);
|
||||
}
|
||||
if (!is_dir($thumbnailsDir)) {
|
||||
mkdir($thumbnailsDir, 0755, true);
|
||||
}
|
||||
|
||||
// Mover archivo subido
|
||||
if (!move_uploaded_file($file['tmp_name'], $uploadPath)) {
|
||||
throw new Exception('Error al guardar el archivo');
|
||||
}
|
||||
|
||||
// Crear thumbnail
|
||||
createThumbnail($uploadPath, $thumbnailPath, 300, 300);
|
||||
|
||||
// Guardar en la base de datos
|
||||
$stmt = $db->prepare("
|
||||
INSERT INTO gallery (nombre, nombre_original, ruta, ruta_thumbnail, hash_md5, tipo_mime, tamano, ancho, alto, usuario_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
$newName,
|
||||
$file['name'],
|
||||
'uploads/' . $newName,
|
||||
'thumbnails/' . $newName,
|
||||
$hash,
|
||||
$mimeType,
|
||||
$file['size'],
|
||||
$width,
|
||||
$height,
|
||||
$userData->userId
|
||||
]);
|
||||
|
||||
$imageId = $db->lastInsertId();
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'duplicate' => false,
|
||||
'image' => [
|
||||
'id' => $imageId,
|
||||
'nombre' => $newName,
|
||||
'ruta' => 'uploads/' . $newName,
|
||||
'ruta_thumbnail' => 'thumbnails/' . $newName,
|
||||
'url' => '/gallery/uploads/' . $newName,
|
||||
'url_thumbnail' => '/gallery/thumbnails/' . $newName
|
||||
]
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'error' => 'Error del servidor: ' . $e->getMessage()]);
|
||||
error_log('Error en upload.php: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Crear thumbnail de una imagen
|
||||
*/
|
||||
function createThumbnail($sourcePath, $destPath, $maxWidth, $maxHeight) {
|
||||
$imageInfo = getimagesize($sourcePath);
|
||||
$width = $imageInfo[0];
|
||||
$height = $imageInfo[1];
|
||||
$mimeType = $imageInfo['mime'];
|
||||
|
||||
// Cargar imagen según el tipo
|
||||
switch ($mimeType) {
|
||||
case 'image/jpeg':
|
||||
$source = imagecreatefromjpeg($sourcePath);
|
||||
break;
|
||||
case 'image/png':
|
||||
$source = imagecreatefrompng($sourcePath);
|
||||
break;
|
||||
case 'image/gif':
|
||||
$source = imagecreatefromgif($sourcePath);
|
||||
break;
|
||||
case 'image/webp':
|
||||
$source = imagecreatefromwebp($sourcePath);
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Tipo de imagen no soportado');
|
||||
}
|
||||
|
||||
// Calcular nuevas dimensiones manteniendo el aspecto
|
||||
$ratio = min($maxWidth / $width, $maxHeight / $height);
|
||||
$newWidth = intval($width * $ratio);
|
||||
$newHeight = intval($height * $ratio);
|
||||
|
||||
// Crear thumbnail
|
||||
$thumbnail = imagecreatetruecolor($newWidth, $newHeight);
|
||||
|
||||
// Preservar transparencia para PNG y GIF
|
||||
if ($mimeType === 'image/png' || $mimeType === 'image/gif') {
|
||||
imagealphablending($thumbnail, false);
|
||||
imagesavealpha($thumbnail, true);
|
||||
$transparent = imagecolorallocatealpha($thumbnail, 255, 255, 255, 127);
|
||||
imagefilledrectangle($thumbnail, 0, 0, $newWidth, $newHeight, $transparent);
|
||||
}
|
||||
|
||||
// Redimensionar
|
||||
imagecopyresampled($thumbnail, $source, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
|
||||
|
||||
// Guardar thumbnail
|
||||
switch ($mimeType) {
|
||||
case 'image/jpeg':
|
||||
imagejpeg($thumbnail, $destPath, 85);
|
||||
break;
|
||||
case 'image/png':
|
||||
imagepng($thumbnail, $destPath, 8);
|
||||
break;
|
||||
case 'image/gif':
|
||||
imagegif($thumbnail, $destPath);
|
||||
break;
|
||||
case 'image/webp':
|
||||
imagewebp($thumbnail, $destPath, 85);
|
||||
break;
|
||||
}
|
||||
|
||||
imagedestroy($source);
|
||||
imagedestroy($thumbnail);
|
||||
}
|
||||
Reference in New Issue
Block a user