El manejo de archivos que superan los 20 GB en entornos web presenta desafíos críticos, especialmente en cuanto a la estabilidad de la conexión y la integridad de los datos. Una solución robusta requiere la implementación de técnicas de fragmentación (chunking), soporte para estructuras de carpetas recursivas y capas de abstracción para múltiples motores de base de datos.
1. Arquitectura del Frontend: Vue 3 y WebUploader
Para garantizar la compatibilidad con diversos navegadores y permitir la carga de archivos masivos, se utiliza una combinación de Vue 3 y WebUploader. La funcionalidad clave es la capacidad de procesar directorios manteniendo su jerarquía original mediante la API webkitGetAsEntry.
// Lógica para el procesamiento de carpetas y cifrado opcional
import WebUploader from 'webuploader';
import CryptoJS from 'crypto-js';
const listaDeArchivos = ref([]);
const procesarCarpeta = (evento) => {
const items = evento.target.files;
const recorrerEntradas = (item, rutaBase) => {
if (item.isFile) {
item.file(archivo => {
// Ejemplo de cifrado de metadatos o contenido
const lector = new FileReader();
lector.onload = (e) => {
const contenidoCifrado = CryptoJS.AES.encrypt(
e.target.result,
'clave-segura-123'
).toString();
listaDeArchivos.value.push({
datos: archivo,
rutaRelativa: rutaBase + archivo.name,
hashCifrado: contenidoCifrado
});
};
lector.readAsDataURL(archivo);
});
} else if (item.isDirectory) {
const lectorDirectorio = item.createReader();
lectorDirectorio.readEntries(entradas => {
entradas.forEach(entrada => {
recorrerEntradas(entrada, rutaBase + item.name + '/');
});
});
}
};
Array.from(items).forEach(item => recorrerEntradas(item, ''));
};
const configurarUploader = () => {
const uploader = WebUploader.create({
server: '/api/recepcion_fragmentos.php',
chunked: true,
chunkSize: 5 * 1024 * 1024, // Bloques de 5MB
threads: 3,
formData: { token: 'auth_token_example' }
});
uploader.on('uploadSuccess', (archivo, respuesta) => {
console.info('Fragmento procesado correctamente:', respuesta);
});
};
2. Procesamiento en el Servidor (PHP)
El backend debe encargarse de recibir cada fragmento, almacenarlo temporalmente y unificarlo una vez que todas las partes han sido transmitidas con éxito. A continuación, se presenta una lógica optimizada para la consolidación de archivos.
<?php
// recepcion_fragmentos.php
$directorioTemporal = "./storage/tmp/" . $_POST['file_id'];
$nombreArchivoFinal = "./storage/final/" . $_POST['file_name'];
if (!file_exists($directorioTemporal)) {
mkdir($directorioTemporal, 0777, true);
}
// Almacenar el fragmento actual
move_uploaded_file($_FILES['file']['tmp_name'], $directorioTemporal . '/' . $_POST['chunk_index']);
$totalFragmentos = (int)$_POST['chunks'];
$fragmentosRecibidos = count(glob("$directorioTemporal/*"));
if ($fragmentosRecibidos === $totalFragmentos) {
$archivoFinal = fopen($nombreArchivoFinal, 'wb');
for ($i = 0; $i < $totalFragmentos; $i++) {
$rutaFragmento = "$directorioTemporal/$i";
$contenido = file_get_contents($rutaFragmento);
fwrite($archivoFinal, $contenido);
unlink($rutaFragmento); // Eliminar fragmento tras unirlo
}
fclose($archivoFinal);
rmdir($directorioTemporal);
echo json_encode(['status' => 'success', 'message' => 'Archivo consolidado']);
} else {
echo json_encode(['status' => 'uploading', 'progress' => ($fragmentosRecibidos / $totalFragmentos) * 100]);
}
?>
3. Abstracción de Base de Datos para Entornos Corporativos
En sistemas que requieren alta compatibilidad (como entornos con bases de datos MySQL, PostgreSQL o sistemas propietarios como Dameng), es imperativo utilizar una fábrica de conexiones basada en PDO.
<?php
class GestorBaseDatos {
public static function conectar($driver, $config) {
try {
switch ($driver) {
case 'mysql':
$dsn = "mysql:host={$config['host']};dbname={$config['db']}";
break;
case 'postgresql':
$dsn = "pgsql:host={$config['host']};dbname={$config['db']}";
break;
case 'oracle':
$dsn = "oci:dbname={$config['host']}/{$config['db']}";
break;
default:
throw new Exception("Driver no soportado");
}
return new PDO($dsn, $config['user'], $config['pass'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
} catch (PDOException $e) {
die("Error de conexión: " . $e->getMessage());
}
}
}
?>
4. Optimización de la Persistencia
Para asegurar que las cargas puedan reanudarse tras un cierre inesperado del navegador o una caída de red, se recomienda:
- Utilizar localStorage en el cliente para registrar el progreso de cada
file_id. - Implementar una verificación previa (pre-flight) en el servidor que informe al cliente qué fragmentos ya existen para evitar retransmisiones innecesarias.
- Configurar el servidor PHP para manejar tiempos de ejecución prolongados (
max_execution_time) y límites de memoria adecuados, aunque el chunking minimiza este impacto.
El uso de herramientas de almacenamiento en la nube, como AWS S3 o Huawei Cloud OBS, puede integrarse reemplazando la lógica de escritura local por los respectivos SDKs, manteniendo la misma estructura de fragmentación en el lado del cliente.