Watermarked download – three-step process and issue log

Steps of the download request, the asynchronous preparation and the streamed delivery, permission re-check, watermark content and fingerprints of issued copies.

Overview

A portal download runs in three steps: request, preparation in the background, then delivery of the file. Bytes move only in the last step, and no watermarked copy is written to web storage.

Data model

Table names carry the installation's own prefix in the database.

TableRole
doc_downloaddownload request (token, user, source, store_id, folder, document, state, expiry)
doc_download_itemissue per file (unique watermark code, SHA-256 fingerprint, skip reason)

Migration: install/migrations/1.1.0/20261029_011_dataroom_store_download.sql.

Process

  1. dlrequest&doc_share_id= (optionally doc_id; without it the whole folder): sign-in check (error_login_required), then downloadRequest(): the folder belongs to the user and is downloadable, for a single file the document is accessible and downloadable too; dlbtdocdownload->request(user_id, 'portal', share_id, doc_id) writes a doc_download row and queues an immediate doc_download job. Response: token, queued.
  2. doc_download background job (prepareQueued(50)): closes expired requests; re-checks permission with the rules valid at that moment (assignment, time window, the request's store, content scope, downloadability of folder and document; for an admin request every active document of the folder); a unique code per file in the issue log; non-watermarkable files are skip; with no issuable file failed (nothing_watermarkable or nothing_allowed), otherwise ready with a 24-hour expiry.
  3. dlstatus (every two seconds): own request only (getDownloadByToken); if the queue has not picked it up within 20 seconds, it runs the preparation itself; an expired finished package is expired. Response: state, files, skipped, and the dlfile URL when ready.
  4. dlfile: token belongs to the user, state ready, and the folder is accessible NOW. dlbtdocdownload->stream(): bytes per file into memory, watermark in memory (PDF: Dlbtwatermark::pdf, image: Dlbtwatermark::image; text: name, ID, date, "Confidential", unique code); one file directly, several as a streamed ZIP (Zipwriter) named after the folder with a table of contents. The SHA-256 fingerprint of every copy is logged (markDownloadIssued) and the download marked (markDownloaded).

The old download route remains: its body starts the shared request and redirects to the portal with the token parameter.