Files, protected files, and storage
Upload, serve, protect, transform, delete, and store files in PocketBase.
Use a file field to attach files to records, then choose whether the files are public or protected. This guide covers the complete file lifecycle and the storage choices available to administrators.
Before you begin
Create a collection with a file field. Set Max Files to 1 for one filename or to at least 2 when a record needs multiple files. The default maximum file size is approximately 5 MB; adjust it in the field options only when your capacity and serving requirements support the larger files.
Upload and manage files
Send a multipart/form-data request through your SDK or the Records create API. In JavaScript, pass File objects under the file field name.
const record = await pb.collection("documents").create({
title: "Project brief",
attachments: [
new File(["draft content"], "brief.txt"),
],
});The response contains the created record and the sanitized filename with a random suffix.
For a multiple-file field, append files with the + suffix and remove selected filenames with the - suffix.
await pb.collection("documents").update("RECORD_ID", {
"attachments+": new File(["revision"], "revision.txt"),
"attachments-": ["brief.txt"],
});Set attachments to [] to remove every file from a multiple-file field. For FormData, use an empty string when clearing the field.
Build the file URL as /api/files/COLLECTION/RECORD_ID/FILENAME. Add ?download=1 to request a download, or add a thumb modifier such as ?thumb=300x200 for supported images.
http://127.0.0.1:8090/api/files/documents/RECORD_ID/brief.png?thumb=300x200WxH crops from the center. WxHt and WxHb crop from the top or bottom; WxHf fits without cropping; 0xH and Wx0 preserve the aspect ratio. If the file is not a supported image or the thumbnail is unavailable, PocketBase returns the original file.
Enable Protected in the file field options, and make the collection's View API rule restrict access to the intended records. Authenticate first, then request a short-lived file token and include it in the file URL.
await pb.collection("users").authWithPassword("reader@example.com", "use-a-local-test-password");
const token = await pb.files.getToken();
const url = pb.files.getURL(record, record.attachments, { token });The token request requires authentication. A protected file is served only when the request satisfies the record View API rule; otherwise the request is denied.
Choose storage
PocketBase stores files locally in pb_data/storage by default. You can switch to an S3-compatible backend, including AWS S3, MinIO, Wasabi, DigitalOcean Spaces, or Vultr Object Storage, from Dashboard > Settings > Files storage. Local storage is a practical default when disk capacity and backups are under your control; external storage is an option when those constraints require it.
Troubleshooting
If a protected request returns insufficient permissions to access the file resource, check the record's View API rule and request a fresh file token after authenticating. If a thumbnail does not appear, verify that the file is an image format supported by the requested modifier; PocketBase returns the original when it cannot produce that thumbnail.
Next steps
Continue with API rules and filters to define who can view protected records, or use the Files API reference for endpoint details.