Skip to content

Bundle files into ZIP

The "Bundle files into ZIP" service task combines multiple file references – for example from previous service tasks, upload activities or form fields – into a single ZIP archive and returns a new file reference to the resulting archive. This is ideal for offering several generated documents as one download or for archiving all artefacts of a process in a single bundle.

This service is the counterpart of “Unzip ZIP file”: its output (files and groups) can be passed in unchanged as input here. Round-trip scenarios such as “unzip → process individual files → zip again” work out of the box.


When to use this service task

  • Bulk download of generated documents: Multiple generated PDFs (e.g. all invoices of a month) are combined into a single archive offered for download.
  • Archival: At the end of a process, all resulting receipts, logs and exports are bundled into one ZIP for long-term storage.
  • Export with folder structure: A data export contains several categories (invoices, bookings, receipts) that are represented as separate folders inside the archive.
  • Round-trip with "Unzip ZIP file": An incoming archive is extracted, individual files are transformed, and the result is zipped again – without having to rebuild the original folder structure manually.

Input parameters

The task accepts the following fields:

{
  "files": [
    {
      "referenceId": "...",
      "filename": "invoice-001.pdf",
      "contentType": "application/pdf"
    }
  ],
  "groups": {
    "invoices": [
      {
        "referenceId": "...",
        "filename": "invoice-002.pdf",
        "contentType": "application/pdf"
      }
    ]
  },
  "output_filename": "archive.zip",
  "compressionLevel": 5,
  "maxFiles": 5000,
  "maxTotalBytes": 2147483648
}

Explanation:

  • files: List of file references placed directly at the root of the ZIP archive (optional). Each entry contains referenceId, filename and contentType.
  • groups: Object whose keys represent folder paths inside the ZIP. The associated list contains file references that will be stored as foldername/filename (optional).
  • output_filename: Name of the generated archive (optional, default: "archive.zip"). The .zip extension is enforced automatically.
  • compressionLevel: Compression level between 0 and 9 (optional, default: 5).
    • 0 – no compression, fastest processing, largest file.
    • 5 – balanced (default).
    • 9 – maximum compression, slowest processing, smallest file.
  • maxFiles: Maximum number of files that may be added to the archive (optional, default: 5000).
  • maxTotalBytes: Maximum total uncompressed size in bytes (optional, default: 2147483648 = 2 GB).

At least one source required

Either files or groups (or both) must contain at least one entry. Without input files the task aborts with an error.


Output

The task returns a single file reference to the generated ZIP archive:

{
  "referenceId": "...",
  "filename": "archive.zip",
  "contentType": "application/zip"
}

Explanation:

  • referenceId: Reference to the generated file in the data lake. It can be passed on to downstream tasks, for example to send the archive via email, upload it to SharePoint/FTP, or attach it to a data object.
  • filename: The actual filename used (always with .zip extension).
  • contentType: Always application/zip.

JSONata examples

Simple case – all files flat in the archive:

{
  "files": $.allPdfs,
  "output_filename": "invoices_2026.zip"
}

With folder structure:

{
  "groups": {
    "invoices": $.invoiceFiles,
    "bookings": $.bookingFiles
  },
  "output_filename": "export.zip"
}

Round-trip – repack the result of "Unzip ZIP file":

{
  "files": $.unzipResult.files,
  "groups": $.unzipResult.groups,
  "output_filename": "repacked.zip"
}

Maximum compression for small archives:

{
  "files": $.documents,
  "compressionLevel": 9,
  "output_filename": "small.zip"
}

Notes

  • Round-trip compatible: The input structure exactly mirrors the output of “Unzip ZIP file”. Extra fields from the unzip output such as count or skipped are simply ignored.
  • Streaming processing: Files are read one by one from the data lake and written directly into the archive. Memory usage stays bounded even with many or large files.
  • Name collisions: If multiple files end up on the same path inside the archive (e.g. two invoice.pdf in the same group), a counter is appended automatically: invoice.pdf, invoice_2.pdf, invoice_3.pdf.
  • Path sanitizing: Leading slashes and path-traversal patterns (..) are stripped from filenames before the entry is written.
  • Extension enforced: If output_filename is provided without a .zip extension, it is added automatically.
  • compressionLevel = 0: Files are only bundled, not compressed. Useful for archives containing already compressed formats (PDF, JPG, PNG) where additional compression offers little benefit but costs time.

Limits and why they exist

The parameters maxFiles and maxTotalBytes act as safeguards against accidentally oversized archives:

  • Memory and runtime protection: Very large ZIPs can exceed the service task's maximum runtime or overwhelm downstream systems (email attachments, uploads).
  • Protection against configuration mistakes: JSONata expressions that unintentionally resolve to a huge list of file references are caught early.
  • maxTotalBytes applies to the uncompressed total size derived from the metadata of the source files. The limit therefore still kicks in even if compression would reduce the final size drastically.

The default values (5000 files, 2 GB) are generous and should rarely need to be changed for typical bulk exports. For particularly large archives the limits can be raised explicitly – keeping in mind the technical constraints of the following steps.


Tip

In combination with “Unzip ZIP file” a complete processing loop can be modelled: an incoming archive is unzipped, each file is transformed or validated inside a multi-instance subprocess, and the result is packed into a new ZIP with the same folder structure. Because both services share the exact same schema, it is enough to pass files and groups straight through.