ReboFilesDocs
Start3
What is ReboFiles
Getting started
Demos to run
Put it in your app6
React component
Headless: your own UI
Without a framework
Styling and themes
Keyboard and accessibility
Languages
Files9
Uploads
Previews and the viewer
Search
Live changes and large folders
Comments
Starred and fields
Versions, trash and space
Download as .zip
Word documents
The server14
The route
Frameworks and sign-in
Who may do what
Storage: S3, GCS, Azure and disk
Checking uploads
Metadata: SQLite and Postgres
Database schema
Sharing and links
Activity and notifications
Hooks, logs and limits
Retention, holds and export
Desktop and other origins
Sync a folder
Going to production
Together1
AI assistants (MCP)
Reference5
Packages
Components and hooks
Client API
HTTP routes
Status and roadmap
↑↓ to move↵ to openEsc to close38 pages

The server Checking uploads

Checking uploads

The bytes go from the browser to the bucket without passing through the server, and the server only lists a file once they are there. So there are two moments to say no: before it is given addresses (beforeUpload), and after its bytes arrived and before anyone sees it (inspect). What is refused at the second is taken out of the bucket.
beforeUpload

Before it goes up

With what the page says of it: its name, type, size and where it goes. Nothing has been sent yet.

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
  },
});

A Refused is answered with its status, code and message; false is a 403. It is asked for each new file and each new version, not for the smaller pictures the page makes of one. The type and size are what the page says: for what they really are, inspect.

inspect

Once its bytes arrived

Asked before the file or the version is kept, with a read of the bytes in the storage. Both storages of the server can read.

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() reads the first 4 KB. It refuses a program (an .exe, a binary of Linux or of a Mac) unless programs: true, and a file whose bytes are not those of its extension: a PNG that is not one, a .docx that is not a zip. only keeps to some types.
  • clamav() sends the bytes to clamd, a megabyte at a time, by its INSTREAM command. A file larger than clamd takes (25 MB unless said) is refused, not let in unscanned.
  • inspectAll(…) asks several in order: the first to refuse refuses.

A file not looked at is not let in. When inspect throws something other than a Refused (clamd down, a time out), the upload is refused with a 503 and its bytes are taken away. The page says so, and the person uploads it again.

Viruses

ClamAV on the server

# 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
Yours

An inspect of your own

Any function: a scanner of your provider, a rule of your own on what may be kept.

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.`);
},
Errors

What people read

CodeStatusWhen
upload-refused403beforeUpload returned false
program-refused422checkType: a program
type-mismatch422checkType: the bytes are not those of the extension
type-refused422checkType: a type not among only
virus-found422clamav: a virus, named in the message
refused-content422inspect returned false
not-scanned · not-inspected503clamav, or inspect, could not look at it