Pregunta
Una aplicación web de escritorio importa archivos de gran tamaño. Los usuarios pueden hacer clic para seleccionar un archivo, arrastrar archivos a una zona de colocación (drop zone) o usar un navegador compatible con showOpenFilePicker(). Diseña el flujo frontend completo, incluyendo detección de características, respaldo (fallback), cancelación, progreso, accesibilidad, privacidad y reintentos. Explica qué capacidades constituyen mejoras progresivas en lugar de dependencias base.
Respuesta de referencia
Utiliza un único modelo de entrada: un File o un file handle legible. La interfaz de usuario solo debe recibir los archivos candidatos, el origen, el tamaño, el tipo y el estado. La base de referencia es un <input type="file"> visible y debidamente etiquetado, ya que goza de amplia disponibilidad; arrastrar y soltar es otra forma de producir el mismo modelo. Si window.showOpenFilePicker existe en un contexto seguro, utilízalo únicamente desde el manejador de un evento de clic del usuario como una mejora progresiva. Si el selector falla, se cancela o se deniega el permiso, mantén disponible la ruta del input en lugar de tratar la excepción como una falta de compatibilidad.
Modela el flujo como idle → selected → validating → reading → uploading → complete, con ramas cancelled y failed. Valida la extensión, el tipo MIME declarado, los límites de tamaño real y el formato de negocio; las verificaciones del cliente ofrecen retroalimentación rápida, mientras que el servidor debe validar nuevamente. Lee archivos grandes en forma de flujos (streams) o fragmentos (slices), cancela lecturas y subidas con AbortController, reintenta únicamente fragmentos reproducibles y muestra los bytes completados junto con una estimación.
Los nombres, las rutas y los contenidos son datos del usuario. Muestra únicamente los metadatos necesarios y mantén el contenido fuera de los registros (logs); revoca las URL de objetos de vista previa con URL.revokeObjectURL(). La zona de colocación necesita una ruta accesible por teclado y mediante un botón convencional, exponiendo el foco, los errores y el progreso a través de elementos semánticos y una región en vivo (live region). El arrastre no debe ser la única operación. Informa al usuario cuándo se subirán los datos y, tras una cancelación, limpia las referencias locales y el trabajo pendiente.
Dificultades clave
showOpenFilePicker() requiere una activación de usuario transitoria, por lo que no puede ejecutarse desde un temporizador, al cargar la página o desde una tarea en segundo plano demorada. Retorna handles, lo cual no implica un permiso de lectura permanente. La detección de características no garantiza el permiso. El atributo accept en un input es una sugerencia, no una verificación de seguridad, y File.type puede estar vacío o ser provisto por el cliente. Los manejadores de eventos drop deben prevenir la navegación predeterminada y gestionar directorios, múltiples archivos y listas sumamente extensas.
Errores comunes
- Tratar la File System Access API como una dependencia base.
- Confiar en una extensión o valor MIME como validación de seguridad del archivo.
- Ocultar el input sin conservar una etiqueta, una vía de acceso por teclado y una ruta para lectores de pantalla.
- Leer un archivo grande completo en memoria antes de subirlo.
- Mostrar "permiso denegado" indistintamente para cancelaciones, errores de formato y fallas de red.
Análisis de compensaciones (trade-offs)
El input representa la base confiable con el mayor alcance, pero carece de operaciones a nivel de handle. El selector puede reducir la selección repetida y habilitar operaciones más enriquecidas con handles, aunque depende de la compatibilidad del navegador, HTTPS, la activación del usuario y los permisos. Arrastrar y soltar mejora el rendimiento en escritorio, pero requiere una alternativa accesible por teclado. La validación en el cliente acorta el tiempo de respuesta; la validación en el servidor constituye el límite de seguridad. La fragmentación (chunking) y la capacidad de reanudación incrementan la complejidad del estado, pero reducen el costo de reintentar transferencias de gran tamaño.
Ejemplo ejecutable
async function chooseFiles(input) {
if (window.showOpenFilePicker && window.isSecureContext) {
try {
const handles = await window.showOpenFilePicker({ multiple: true });
return Promise.all(handles.map((handle) => handle.getFile()));
} catch (error) {
if (error?.name !== "AbortError") throw error;
}
}
return Array.from(input.files ?? []);
}Ejecuta esto desde un manejador de eventos de clic del usuario. El código en producción también debe restringir el tipo, la cantidad y el tamaño, así como mapear las fallas a estados visibles para el usuario. Un manejador drop puede convertir event.dataTransfer.files al mismo arreglo y reutilizar la máquina de estados de validación y subida.
Preguntas de seguimiento del entrevistador
¿Por qué no llamar a showOpenFilePicker() durante la carga de la página? La API requiere una activación transitoria del usuario, por lo que las llamadas demoradas o en segundo plano pueden ser rechazadas. ¿Acaso accept detiene el malware? No. Es una sugerencia para el selector; las comprobaciones de seguridad corresponden al servidor. ¿Por qué mantener un mecanismo de respaldo? La compatibilidad del navegador y los permisos pueden variar, por lo que la funcionalidad base debe operar con el input universalmente disponible.
Respuestas de seguimiento
¿Cómo se prueban las rutas de respaldo?
Prueba por separado un navegador no compatible, un contexto no seguro, la cancelación y la denegación de permisos; verifica que la ruta mediante el input aún complete la importación.
¿Cómo se previene el agotamiento de memoria?
Utiliza File.slice() o streams, limita la concurrencia, sube fragmentos y cancela el controlador cuando el usuario aborte la operación.
¿Cómo se hace accesible el flujo?
Conserva una etiqueta y un botón reales, haz que la zona de colocación sea enfocable, permite que el teclado active el input y asocia los errores y el progreso con texto y una región en vivo (live region).
¿Qué métricas demuestran que funciona?
Monitorea las tasas de éxito, cancelación, fallas de validación, finalización exitosa tras reintentos, tiempo hasta el primer progreso y tasas de respaldo por navegador, sin registrar el contenido de los archivos.