ReboFilesDocs
Empezar3
Qué es ReboFiles
Primeros pasos
Demos para ejecutar
Ponlo en tu app6
Componente de React
Headless: tu propia interfaz
Sin framework
Estilos y temas
Teclado y accesibilidad
Idiomas
Archivos9
Subidas
Vistas previas y el visor
Búsqueda
Cambios en vivo y carpetas grandes
Comentarios
Destacados y campos
Versiones, papelera y espacio
Descargar como .zip
Documentos de Word
El servidor14
La ruta
Frameworks e inicio de sesión
Quién puede hacer qué
Almacenamiento: S3, GCS, Azure y disco
Revisar las subidas
Metadatos: SQLite y Postgres
Esquema de la base de datos
Compartir y enlaces
Actividad y notificaciones
Ganchos, registros y límites
Retención, bloqueos y exportación
Escritorio y otros orígenes
Sincronizar una carpeta
Ir a producción
En equipo1
Asistentes de IA (MCP)
Referencia5
Paquetes
Componentes y hooks
API del cliente
Rutas HTTP
Estado y hoja de ruta
↑↓ para moverte↵ para abrirEsc para cerrar38 páginas

El servidor Revisar las subidas

Revisar las subidas

Los bytes van del navegador al bucket sin pasar por el servidor, y el servidor solo lista un archivo cuando ya están ahí. Así que hay dos momentos para decir que no: antes de darle direcciones (beforeUpload), y cuando llegaron sus bytes y antes de que nadie lo vea (inspect). Lo rechazado en el segundo se quita del bucket.
beforeUpload

Antes de que suba

Con lo que la página dice de él: nombre, tipo, tamaño y adónde va. Aún no se ha enviado nada.

import { Refused, createDriveHandler } from '@rebofiles/server';

createDriveHandler({
  // …
  beforeUpload: (upload) => {
    if (upload.type.startsWith('video/')) throw new Refused(415, 'no-videos', 'Videos go to the media library.');
    if (upload.parent === null && upload.purpose === 'file') return false; // nothing loose at the top
  },
});

Un Refused se responde con su estado, código y mensaje; false es un 403. Se pregunta por cada archivo nuevo y cada versión nueva, no por las imágenes pequeñas que hace la página. El tipo y el tamaño son los que dice la página: para lo que de verdad son, inspect.

inspect

Cuando llegaron sus bytes

Se pregunta antes de guardar el archivo o la versión, con una lectura de los bytes del almacenamiento. Los dos almacenamientos del servidor pueden leer.

import { checkType, clamav, createDriveHandler, inspectAll } from '@rebofiles/server';

createDriveHandler({
  // …
  // A program called photo.png, a PDF called .docx: refused. Then ClamAV, on its TCP socket.
  inspect: inspectAll(checkType(), clamav({ host: '127.0.0.1', port: 3310 })),
});
  • checkType() lee los primeros 4 KB. Rechaza un programa (un .exe, un binario de Linux o de Mac) salvo con programs: true, y un archivo cuyos bytes no son los de su extensión: un PNG que no lo es, un .docx que no es un zip. only limita a algunos tipos.
  • clamav() envía los bytes a clamd, un megabyte cada vez, con su comando INSTREAM. Un archivo mayor de lo que acepta clamd (25 MB si no se dice) se rechaza, no se deja pasar sin revisar.
  • inspectAll(…) pregunta a varios en orden: el primero que rechaza, rechaza.

Un archivo sin revisar no entra. Cuando inspect lanza algo que no es un Refused (clamd caído, un tiempo agotado), la subida se rechaza con un 503 y se quitan sus bytes. La página lo dice, y la persona lo vuelve a subir.

Virus

ClamAV en el servidor

# Ubuntu: the daemon, its signatures kept fresh, and a socket the server reaches
sudo apt install clamav-daemon
echo 'TCPSocket 3310' | sudo tee -a /etc/clamav/clamd.conf
echo 'TCPAddr 127.0.0.1' | sudo tee -a /etc/clamav/clamd.conf
sudo systemctl restart clamav-daemon

# Or in Docker
docker run -d -p 3310:3310 clamav/clamav
Tuyo

Un inspect propio

Cualquier función: un escáner de tu proveedor, una regla propia sobre lo que se puede guardar.

inspect: async (upload, drive) => {
  if (upload.purpose === 'rendition') return;     // a smaller picture the page made
  const head = await upload.read({ from: 0, to: 4100 });
  const verdict = await myScanner(upload.key, head);
  if (verdict === 'reject') throw new Refused(422, 'rejected', `${upload.name} was not kept.`);
},
Errores

Lo que lee la gente

CódigoEstadoCuándo
upload-refused403beforeUpload devolvió false
program-refused422checkType: un programa
type-mismatch422checkType: los bytes no son los de la extensión
type-refused422checkType: un tipo fuera de only
virus-found422clamav: un virus, nombrado en el mensaje
refused-content422inspect devolvió false
not-scanned · not-inspected503clamav, o inspect, no pudo revisarlo

El drive dice cada uno en el idioma de la persona, por su código.