Skip to Content

Scripting example – Batch files for download

This Plugin supports the ability to download multiple files from a Multi-row Panel or Board Panel at once. On the Business Object event executing, the Plugin will loop through all Business Object or table records to identify and batch together the appropriate files to make available in a singular download.

When the Plugin runs, it essentially grabs all of the File and corresponding FileName values and puts them into a zip file. The name of the zip file generated when the Plugin is finished will be: "MM/dd/yyyy h:mm tt".zip", which reflects the datetime that it ran and appends the .zip extension.

With the script example provided, the script runs on a Table or Business Object independent of panel or UI level bindings. This means that a panel level bind or control bind does not affect the underlying table for the Plugin. This also means that everything that you want to do, including bindings on the panel or table, has to be done at the Business Object/Table level.

Use case

This Plugin is useful when you have a panel in an app where you want to make multiple files available for download in a single action.


This Plugin requires that you have two tables or Business Objects existing, and both must have File and FileName columns. One of these represents where the Plugin is reading from, and the other represents where the Plugin is inserting into.

Implementation preferences

You will want to review and modify the following syntax in the script, to substitute the UUIDs on the plugin to reflect the actual UUIDs of the tables or Business Objects you are referencing in your app.

var importFileTableFilter = tableService.GetTable(Guid.Parse("{{UUID of the table that contains the files that are going to be zipped}}")).CreateFilter();

var importZipTableFilter = tableService.GetTable(Guid.Parse("{{UUID of the table that the ZIP File is going to be inserted}}")).CreateFilter();

Plugin references


It is possible to modify the Plugin script to grab other FileName and File content columns, but typically the naming methodology states that the content column be "File" and the name of the file is "FileName".

Column Data Type Description
FileName String Column containing name and extension of File.
File Binary Column with File Content.

Script example

using System.IO;
using System.IO.Compression;
using Vinyl.Sdk.Events;
using Vinyl.Sdk.Filtering;
using System.Linq;
using Vinyl.Sdk;
using System;

var tableService = Services.GetService<ITableService>();
var eventService = Services.GetService<IEventService>();

var importFileTableFilter = tableService.GetTable(Guid.Parse("Table UUID containing files to be compressed")).CreateFilter();
EventTable readFileTable = await eventService.InvokeEventAsync(importFileTableFilter, "filter");
importFileTableFilter.Limit = 0;
EventTable importFileTable = await eventService.InvokeFilterEventAsync(importFileTableFilter);
EventRow rowFile = await eventService.InvokeNewEventAsync(importFileTable);

var importZipTableFilter = tableService.GetTable(Guid.Parse("Table UUID where ZIP file will be inserted")).CreateFilter();
importZipTableFilter.Limit = 0;
EventTable importZipTable = await eventService.InvokeFilterEventAsync(importZipTableFilter);
EventRow rowZip = await eventService.InvokeNewEventAsync(importZipTable);

byte[] fileBytes;
var compressedFileStream = new MemoryStream();
string inspectionID;

using (compressedFileStream)
    compressedFileStream.Seek(0, SeekOrigin.Begin);
    using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, false))
       foreach (EventRow row1 in (EventTable)readFileTable)

                //Create a zip entry for each attachment
                var zipEntry = zipArchive.CreateEntry(row1["FileName"].GetValueAsString());

                //Get the stream of the attachment
                using (var originalFileStream = new MemoryStream((byte[])row1["File"].Value))
                    using (var zipEntryStream = zipEntry.Open())
                        //Copy the attachment stream to the zip entry stream

  fileBytes = compressedFileStream.ToArray();

rowZip["FileName"].Value = DateTime.Now.ToString("MM/dd/yyyy h:mm tt") + ".zip";

rowZip["File"].Value = fileBytes;

await eventService.InvokeInsertEventAsync(rowZip);