up
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* GET /api/lab/descargar_orden.php?file=nombre_archivo.pdf
|
||||
* Sirve archivos de órdenes médicas con el Content-Type correcto.
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
requireMethod('GET');
|
||||
|
||||
$filename = $_GET['file'] ?? '';
|
||||
|
||||
// Validar: solo nombre de archivo sin rutas (evitar path traversal)
|
||||
if (!$filename || $filename !== basename($filename) || strpos($filename, '..') !== false) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Archivo inválido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Solo archivos con prefijo de orden (seguridad adicional)
|
||||
if (!preg_match('/^orden_[a-zA-Z0-9_]+\.[a-zA-Z0-9]+$/', $filename)) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Acceso denegado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$path = realpath(__DIR__ . '/../../uploads/media/' . $filename);
|
||||
$base = realpath(__DIR__ . '/../../uploads/media');
|
||||
|
||||
// Verificar que el archivo esté dentro del directorio permitido
|
||||
if (!$path || !$base || strpos($path, $base) !== 0 || !is_file($path)) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Archivo no encontrado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Detectar MIME real
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mime = finfo_file($finfo, $path);
|
||||
finfo_close($finfo);
|
||||
|
||||
// Mapa de extensiones como fallback
|
||||
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
$mimeMap = [
|
||||
'pdf' => 'application/pdf',
|
||||
'doc' => 'application/msword',
|
||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'jpg' => 'image/jpeg',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'png' => 'image/png',
|
||||
'gif' => 'image/gif',
|
||||
'webp' => 'image/webp',
|
||||
];
|
||||
|
||||
if (!$mime || $mime === 'application/octet-stream') {
|
||||
$mime = $mimeMap[$ext] ?? 'application/octet-stream';
|
||||
}
|
||||
|
||||
// Tipos que el navegador puede mostrar inline
|
||||
$inlineTypes = ['application/pdf', 'image/jpeg', 'image/png', 'image/gif', 'image/webp'];
|
||||
$disposition = in_array($mime, $inlineTypes) ? 'inline' : 'attachment';
|
||||
|
||||
header('Content-Type: ' . $mime);
|
||||
header('Content-Disposition: ' . $disposition . '; filename="' . rawurlencode($filename) . '"');
|
||||
header('Content-Length: ' . filesize($path));
|
||||
header('Cache-Control: private, max-age=3600');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
|
||||
readfile($path);
|
||||
exit;
|
||||
+1
-1
@@ -580,7 +580,7 @@ async function verDomicilio(id) {
|
||||
<i class="fas fa-external-link-alt me-1"></i>Ver ficha orden #${dom.orden_id}
|
||||
</a>`;
|
||||
if (lf) return `
|
||||
<a href="${url}" target="_blank" download
|
||||
<a href="api/lab/descargar_orden.php?file=${encodeURIComponent(lf)}" target="_blank"
|
||||
class="btn btn-sm btn-outline-secondary w-100 mb-1">
|
||||
<i class="fas fa-file-download me-1"></i>Abrir / Descargar archivo
|
||||
</a>
|
||||
|
||||
@@ -936,13 +936,12 @@ async function cargarFormulario(id) {
|
||||
$('tb-categoria').value = f.categoria;
|
||||
$('tb-firma').checked = !!f.permite_firma;
|
||||
$('tb-firma-req').checked = !!f.requiere_firma;
|
||||
const _firmaCampo = (_campos || []).find(c => c.tipo === 'firma');
|
||||
_campos = f.esquema_decoded || [];
|
||||
const _firmaCampo = _campos.find(c => c.tipo === 'firma');
|
||||
const _fModos = _firmaCampo?.modos || ['canvas','foto'];
|
||||
$('tb-firma-canvas').checked = _fModos.includes('canvas');
|
||||
$('tb-firma-foto').checked = _fModos.includes('foto');
|
||||
|
||||
_campos = f.esquema_decoded || [];
|
||||
|
||||
// Campos doc
|
||||
const tieneOverride = !!(f.doc_encabezado || f.doc_logo_base64 || f.doc_color);
|
||||
$('tb-usar-global').checked = !tieneOverride;
|
||||
|
||||
Reference in New Issue
Block a user