annie.pages.download ==================== .. py:module:: annie.pages.download .. autoapi-nested-parse:: Save a generated document to the *user's* machine, with their choice of folder and name. Annie's server runs where the data is — often inside a Docker container — so a server-side folder picker would browse the wrong filesystem. The browser is where the person is, so the save happens there: Chromium browsers (Chrome, Edge, Brave, ...) open the operating system's native *Save as* dialog through the File System Access API, starting in the user's Documents folder with the suggested name prefilled. Browsers without it (Firefox, Safari) fall back to a normal download using the suggested name. The content is generated on the server, fetched by the browser from a small route, and written to disk there — server → browser → disk — so local runs and Docker behave identically. Attributes ---------- .. autoapisummary:: annie.pages.download.MIME_TYPES Functions --------- .. autoapisummary:: annie.pages.download.sanitize_filename annie.pages.download.save_from_url_js annie.pages.download.attach_save annie.pages.download.export_menu_item Module Contents --------------- .. py:data:: MIME_TYPES :type: dict[str, str] Extension → MIME type for the formats Annie exports. .. py:function:: sanitize_filename(name: str, *, extension: str, default_stem: str) -> str Make ``name`` a safe file name that ends in ``.extension``. Path separators and characters illegal on Windows are replaced, surrounding dots and spaces trimmed, an empty result falls back to ``default_stem``, and the extension is forced (added if missing, never doubled). :param name: The name the user typed (may be empty or contain a path). :param extension: The required extension without the dot, e.g. ``"csv"``. :param default_stem: Stem to use when ``name`` has nothing usable. :returns: A file name such as ``annie_events_clip1.csv``. .. py:function:: save_from_url_js(filename: str, url: str, mime: str) -> str Return a click handler that fetches ``url`` and saves it where the user picks. The handler runs client-side *inside the click*: it fetches the file first (a local, millisecond request, well inside the browser's transient-activation window), then opens the native Save dialog with ``filename`` prefilled and writes the file. A ``204`` response means "nothing to export" and shows a notice instead of an empty file. Cancelling the dialog is silent. Browsers without ``showSaveFilePicker`` (Firefox, Safari) fall back to a normal download under ``filename``. :param filename: Suggested file name, already sanitised. :param url: Same-origin URL returning the file's content (text or binary). :param mime: MIME type, e.g. ``"text/csv"``. :returns: A JavaScript arrow function (as a string) for ``Element.on(..., js_handler=...)``. .. py:function:: attach_save(element: nicegui.ui.element, *, filename: str, url: str, extension: str) -> None Make clicking ``element`` open the native Save dialog straight away. :param element: A button or menu item. :param filename: Default file name offered in the Save dialog. :param url: Same-origin URL serving the file (see :func:`save_from_url_js`). :param extension: File extension without the dot (selects the MIME type). .. py:function:: export_menu_item(label: str, *, filename: str, url: str, extension: str) -> nicegui.ui.menu_item Add a menu entry that opens the native Save dialog straight away when clicked. :param label: Menu text. :param filename: Default file name offered in the Save dialog. :param url: Same-origin URL serving the file (see :func:`save_from_url_js`). :param extension: File extension without the dot (selects the MIME type). :returns: The created menu item.