subir mas de un archivo, reprogramados
This commit is contained in:
+108
-75
@@ -1,99 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
* API: Subir archivo de orden médica desde el modal de agendamiento
|
||||
* API: Subir archivos de orden médica desde el modal de agendamiento
|
||||
*
|
||||
* POST (multipart/form-data) con campo 'file'
|
||||
* Devuelve: { success, local_file, file_name, file_size, mime }
|
||||
* POST (multipart/form-data):
|
||||
* - files[] : uno o varios archivos (también acepta 'file' singular para retrocompat)
|
||||
* - domicilio_id : (opcional) vincula los archivos a un domicilio creando registros en lab_ordenes_medicas
|
||||
* - paciente_id : (opcional, requerido si domicilio_id se usa)
|
||||
*
|
||||
* Devuelve: { success, archivos: [{local_file, file_name, file_size, mime, orden_id?}] }
|
||||
* + local_file (retrocompat: primer archivo)
|
||||
*/
|
||||
require_once __DIR__ . '/../../config/config.php';
|
||||
require_once __DIR__ . '/../../classes/Database.php';
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
requireMethod('POST');
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
|
||||
requireAuthentication();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'error' => 'Método no permitido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (empty($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
|
||||
$errCode = $_FILES['file']['error'] ?? -1;
|
||||
echo json_encode(['success' => false, 'error' => 'No se recibió ningún archivo (código ' . $errCode . ')']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = $_FILES['file'];
|
||||
|
||||
// Validar tamaño máximo: 10 MB
|
||||
if ($file['size'] > 10 * 1024 * 1024) {
|
||||
echo json_encode(['success' => false, 'error' => 'El archivo supera el tamaño máximo permitido (10 MB)']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Validar tipo MIME real (no confiar solo en la extensión del cliente)
|
||||
$allowedMimes = [
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/gif',
|
||||
'image/webp',
|
||||
'application/pdf',
|
||||
'application/msword',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
'image/gif' => 'gif',
|
||||
'image/webp' => 'webp',
|
||||
'application/pdf' => 'pdf',
|
||||
'application/msword' => 'doc',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
|
||||
'application/vnd.ms-excel' => 'xls',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
|
||||
'text/plain' => 'txt',
|
||||
'text/csv' => 'csv',
|
||||
];
|
||||
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mime = finfo_file($finfo, $file['tmp_name']);
|
||||
finfo_close($finfo);
|
||||
|
||||
if (!in_array($mime, $allowedMimes, true)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Tipo de archivo no permitido (' . $mime . ')']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Generar nombre único y seguro
|
||||
$origExt = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
||||
$origExt = preg_replace('/[^a-z0-9]/', '', $origExt);
|
||||
if (!$origExt) {
|
||||
$mimeToExt = [
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
'image/gif' => 'gif',
|
||||
'image/webp' => 'webp',
|
||||
'application/pdf' => 'pdf',
|
||||
'application/msword' => 'doc',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
|
||||
// Normalizar: acepta files[] o file (retrocompat)
|
||||
$rawFiles = [];
|
||||
if (!empty($_FILES['files']['name'][0])) {
|
||||
// files[] (múltiples)
|
||||
$count = count($_FILES['files']['name']);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$rawFiles[] = [
|
||||
'name' => $_FILES['files']['name'][$i],
|
||||
'tmp_name' => $_FILES['files']['tmp_name'][$i],
|
||||
'error' => $_FILES['files']['error'][$i],
|
||||
'size' => $_FILES['files']['size'][$i],
|
||||
];
|
||||
}
|
||||
} elseif (!empty($_FILES['file']['tmp_name'])) {
|
||||
// file (singular, retrocompat)
|
||||
$rawFiles[] = [
|
||||
'name' => $_FILES['file']['name'],
|
||||
'tmp_name' => $_FILES['file']['tmp_name'],
|
||||
'error' => $_FILES['file']['error'],
|
||||
'size' => $_FILES['file']['size'],
|
||||
];
|
||||
$origExt = $mimeToExt[$mime] ?? 'bin';
|
||||
}
|
||||
|
||||
$newName = 'orden_' . date('Ymd_His') . '_' . bin2hex(random_bytes(4)) . '.' . $origExt;
|
||||
if (empty($rawFiles)) {
|
||||
jsonError('No se recibió ningún archivo');
|
||||
}
|
||||
|
||||
$uploadDir = realpath(__DIR__ . '/../../uploads/media');
|
||||
if (!$uploadDir) {
|
||||
// Intentar crear el directorio si no existe
|
||||
@mkdir(__DIR__ . '/../../uploads/media', 0755, true);
|
||||
$uploadDir = realpath(__DIR__ . '/../../uploads/media');
|
||||
}
|
||||
|
||||
if (!$uploadDir || !is_writable($uploadDir)) {
|
||||
echo json_encode(['success' => false, 'error' => 'El directorio de uploads no está disponible']);
|
||||
exit;
|
||||
jsonError('El directorio de uploads no está disponible');
|
||||
}
|
||||
|
||||
$destPath = $uploadDir . DIRECTORY_SEPARATOR . $newName;
|
||||
$domicilioId = isset($_POST['domicilio_id']) ? (int)$_POST['domicilio_id'] : 0;
|
||||
$pacienteId = isset($_POST['paciente_id']) ? (int)$_POST['paciente_id'] : 0;
|
||||
$om = ($domicilioId && $pacienteId) ? new OrdenMedica() : null;
|
||||
$adminId = adminId();
|
||||
|
||||
if (!move_uploaded_file($file['tmp_name'], $destPath)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Error al guardar el archivo en el servidor']);
|
||||
exit;
|
||||
$archivos = [];
|
||||
|
||||
foreach ($rawFiles as $file) {
|
||||
if ($file['error'] !== UPLOAD_ERR_OK) {
|
||||
continue; // saltar archivos con error de upload
|
||||
}
|
||||
|
||||
// Validar tamaño máximo: 10 MB
|
||||
if ($file['size'] > 10 * 1024 * 1024) {
|
||||
jsonError('El archivo "' . basename($file['name']) . '" supera el límite de 10 MB');
|
||||
}
|
||||
|
||||
// Validar tipo MIME real
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mime = finfo_file($finfo, $file['tmp_name']);
|
||||
finfo_close($finfo);
|
||||
|
||||
if (!array_key_exists($mime, $allowedMimes)) {
|
||||
jsonError('Tipo de archivo no permitido: ' . $mime);
|
||||
}
|
||||
|
||||
// Generar nombre único y seguro
|
||||
$origExt = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
||||
$origExt = preg_replace('/[^a-z0-9]/', '', $origExt);
|
||||
if (!$origExt) {
|
||||
$origExt = $allowedMimes[$mime];
|
||||
}
|
||||
|
||||
$newName = 'orden_' . date('Ymd_His') . '_' . bin2hex(random_bytes(4)) . '.' . $origExt;
|
||||
$destPath = $uploadDir . DIRECTORY_SEPARATOR . $newName;
|
||||
|
||||
if (!move_uploaded_file($file['tmp_name'], $destPath)) {
|
||||
jsonError('Error al guardar el archivo en el servidor');
|
||||
}
|
||||
|
||||
$ordenId = null;
|
||||
if ($om) {
|
||||
// Crear registro en lab_ordenes_medicas vinculado al domicilio
|
||||
$ordenId = $om->crear([
|
||||
'paciente_id' => $pacienteId,
|
||||
'domicilio_id' => $domicilioId,
|
||||
'local_file' => $newName,
|
||||
], $adminId);
|
||||
}
|
||||
|
||||
$archivos[] = [
|
||||
'local_file' => $newName,
|
||||
'file_name' => $file['name'],
|
||||
'file_size' => $file['size'],
|
||||
'mime' => $mime,
|
||||
'orden_id' => $ordenId,
|
||||
];
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'local_file' => $newName,
|
||||
'file_name' => $file['name'],
|
||||
'file_size' => $file['size'],
|
||||
'mime' => $mime,
|
||||
if (empty($archivos)) {
|
||||
jsonError('No se pudo procesar ningún archivo');
|
||||
}
|
||||
|
||||
jsonOk([
|
||||
'archivos' => $archivos,
|
||||
'local_file' => $archivos[0]['local_file'], // retrocompat
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user