Skip to content

Exports

Lists can be exported as Excel (.xlsx) or CSV. The export contains what the user sees: search, filters, sort and the visible columns.

final class DealResource extends Resource
{
protected bool $exportable = true; // adds the permission "deals.export"
}

The export button appears in the toolbar for users with <slug>.export. Records a policy refuses to show are left out of the file, as on the detail page.

Rows What happens
up to exportSyncLimit (1000) the file is created right away and downloaded
more a queue job creates the file; the user gets a notification with the download link
more than exportMaxRows (100 000) rejected, the user is asked to filter the list

Large exports need a queue worker (codeigniter4/queue, database handler):

Terminal window
php spark migrate --all # queue tables, anvil_exports
php spark queue:work anvil # e.g. as a systemd service or supervisor program

The queue name is Config\Anvil::$exportQueue (anvil); Anvil registers its job handler with the queue itself.

The job runs on behalf of the requesting user (Anvil\Security\RunAs): the tenant, scopeQuery() and permissions are the same as in the list, and the export permission is checked again before the file is written.

  • Files are stored outside of the web root (WRITEPATH/anvil/exports, Config\Anvil::$exportPath) under random names.
  • Downloads go through /<panel>/_export/<uuid>. Only the user who requested an export can download it, in the same tenant and panel, while they still have the export permission, and for exportTtl seconds (24 hours). Downloads are sent with Cache-Control: no-store and Content-Security-Policy: sandbox, and are rate limited.
  • A queued export runs in the tenant of the export; if the user left the tenant meanwhile, it fails. A failed export leaves no partial file.
  • php spark anvil:prune deletes expired and failed exports (and old, read notifications, old API access log entries and stored API answers); schedule it daily.
  • Each column contributes Column::exportValue(): numeric, money and count columns are numbers; other columns are the text shown in the list (labels, formatted dates). Own columns can override it, see Extending.
  • Excel cells are always written as text or numbers, never as formulas. In CSV files, values starting with =, +, -, @, |, %, tab, carriage return, line feed or their full-width forms get a leading apostrophe, so spreadsheets do not run them as formulas (CSV injection).
  • CSV files use UTF-8 with BOM and the separator of the locale (; with a decimal comma, otherwise ,).

Every export request (export.requested, with resource, format, rows, search and filters) and every download (export.downloaded) is written to the audit log.