Stable URL

File managerCommunity Edition+

Files managed by a NocoBase storage engine are accessed through a stable URL. The URL first reaches NocoBase, where the file record and access permissions are checked, and then redirects to the actual URL generated by the storage engine.

URL format

/files/<app>/<dataSource>/<collection>/<id><extname>

For example:

/files/main/main/attachments/42.pdf

When APP_PUBLIC_PATH=/nocobase is configured, the URL starts with /nocobase/files/. The path identifies the app, data source, file collection, record ID, and extension. The ID and extension cannot be changed after creation, which keeps the URL stable for the lifetime of the record.

URL variants

PurposeURLBehavior
Open or embed/files/.../42.pdfChecks permission and redirects to the actual file URL
Preview/files/.../42.png?preview=1Redirects to the preview or thumbnail URL
Download/files/.../42.pdf?download=1Redirects with download semantics
Office preview/files/.../42.xlsx?temporaryAccessToken=...Allows Microsoft Office Online Viewer to fetch one file for a short time
Tip

Use the url and preview values returned by NocoBase. Application code normally should not construct /files URLs or their query parameters.

Behavior across NocoBase

  • Attachment fields and file collections return stable URLs after upload and when records are queried
  • HTTP API responses no longer expose local paths, storage domains, or presigned download URLs
  • Markdown uploads store the stable URL, including files in private S3, OSS, COS, or S3 Pro storage
  • Attachment URL fields store a stable URL for managed uploads, while manually entered external URLs remain unchanged
  • Image, PDF, audio, video, and text previews use the stable URL and the current NocoBase login session
  • Public forms grant limited access to files uploaded in the current public-form browser session; this does not create a generally public link

Office preview

Microsoft Office Online Viewer fetches the file from Microsoft servers and cannot use the user's NocoBase cookie. When the user opens an Office preview, NocoBase first checks the user's file permission and then issues a temporary URL for that file.

The URL is valid for 10 minutes by default. TEMPORARY_FILE_ACCESS_EXPIRES_IN may be set from 5 to 10 minutes. It is requested again when the preview is reopened and must never be saved in an attachment field, Markdown content, or a business record.

Permissions and redirects

Logged-in requests use the current app credentials and role. After permission is granted, NocoBase responds with 302 and redirects to the local or object-storage URL.

Stable URLs support GET and HEAD. Other methods return 405. A command-line client must follow redirects, for example:

curl -L \
  -H "Authorization: Bearer <JWT>" \
  "https://example.com/files/main/main/attachments/42.pdf"

Important notes

  • Stable does not mean public; recipients still need permission to view the file
  • Deleting the record or changing its app, data source, or collection context invalidates the old URL
  • Do not persist temporaryAccessToken or use it as a sharing link
  • Do not cache the 302 Location as a permanent URL because storage signatures can expire
  • Do not rewrite the app, data source, collection, ID, or extension in the path
  • Reverse proxies must forward the /files/ route under APP_PUBLIC_PATH to NocoBase. For subpath deployments, keep a compatible root-level /files/ route as well. Configurations generated by the NocoBase CLI include both routes automatically
  • Deployments where the pages access the API cross-origin (with API_BASE_URL pointing to another origin) must add the page origin to CORS_ORIGIN_WHITELIST; otherwise the login cookie is never stored and stable URLs return 403 for lack of credentials. See Environment Variables
  • Use a different hostname for each independent NocoBase service instead of separating services only by port. Browser cookies are not isolated by port; see Production Environment Deployment
  • Sub-apps in the same NocoBase deployment are distinguished by app name and do not need separate hostnames. However, an independent service on another port still needs hostname isolation if it contains a main app or sub-app with the same name
  • Custom fetch() code may also need object-storage CORS after following the redirect
  • Use a dedicated sharing or public-access feature when a long-lived public link is required