Written by Barbara Cooney and Eric Luce

Use Case

When you need to store a significant amount of container data, we have a solution that allows you to store the files in the cloud rather than worry about disk space. Curious how we do it? Read on.

​Container storage options

Embedded

Container data is usually embedded in the FileMaker file, so that your file does not have any dependencies. Everything is in one place so it’s easy to move around. However, if you store more than 40 gigabytes of container data, embedding quickly inflates the size of your FileMaker solution and slows down backups.

External Open

Container data is separate from the FileMaker solution, yet FileMaker handles the links from a record to its container information. You have the ability to customize the path to your container data and can strategically define the folder structure so it’s meaningful.

However, you should not  edit container data from outside of FileMaker. While your backups will be more efficient you’ll need to separately back up the container data.

External Secure

As with External Open, container data is separate from the FileMaker solution with the addition of encryption. You do not have any control over the subdirectories created to store the container data and FileMaker will randomly distribute the files across these directories. 

Linked

Linked storage is when you store container data outside of FileMaker’s management. You store a url to the hosted file on any of several document management system (DMS) providers. Some popular ones are:

  • Microsoft SharePoint
  • Box
  • Dropbox Business
  • Google Drive
  • Amazon S3

Wrapped around these DMS are file upload tools:

  • Transloadit
  • Uppy
  • Uploadcare

We chose Uploadcare because it provides all of the tools we need in an easy-to-use service. They provide a JavaScript widget to upload their files to a CDN (much like S3) to store the files and an API to crop, resize, and much more on the fly—just by adding some extra bits to the URL they provide. If you still need raw S3 for any reason, files stored in Uploadcare can be backed up to an S3 bucket.

Integration components

Web Dev

For this integration, we chose to use a hosted web portal displayed in a FM webviewer. This simply means that the JavaScript code is hosted on a website instead of inside the FileMaker file itself. While this technique doesn’t work if you need to support an offline workflow, it does make the integration and deployment of changes much simpler. Plus, now that we’ve opened the door to a web framework, we have the option to add serverless functions (lambda) or build our own APIs if we ever need to extend the functionality.

The tech stack is a Next.js web app hosted on Vercel. Within our web app, we’ll create a secret page that only loads if you pass a secret key in the URL. Then, we’ll point our web viewer to that URL and the FileMaker native functions will be injected into the web code. This means that we can still run a direct communication between the web code and FileMaker without using the Data API. This helps to increase the speed of fetching data and won’t count against the Data API limit on our server.

Prerequisites:

To do this on your own, you’ll need to be comfortable using an IDE for web development (VSCode) and a git workflow. We recommend a free GitHub account and a free Vercel account for easy deployment of your web app. It’s also helpful to have a basic understanding of the React and Next.js frameworks (links to their getting started guides provided).

Steps:

  • Setup a new Next.js project
  • Commit your code to a get repository
  • Connect your git repository to Vercel for automatic deployments
  • Within Next.js, add a page for your uploader.
    • (optional) add the getServerSideProps function to redirect away from the upload page if the secret key was not passed in as a query parameter
  • Integrate the Uploadcare React widget to this page. Follow their getting started guide for this
    • Add a function to call when the upload is complete. Within that function, call FileMaker.PerformScript() to pass the result of the uploader back to a script for storing / processing

FileMaker

Here’s an overview of the basic components that you’ll need on the FileMaker side.

Document table

We typically do not scatter container fields across a solution. Instead, we relate any record to a single document table so that we minimize duplication of code and have one location for all container data. This approach is helpful whether you link data or use FileMaker’s native storage methods. Sometimes it’s beneficial to have container data in a separate FileMaker file that only has one document table, as centralized container data management is the best practice.  Having a dedicated table for ‘documents’ or a separate file unburdens other files and reduces their backup time.

Here are the core fields we suggest you include in the document table:

  • FileName, text
  • Id, UUID primary key
  • Thumbnail, container External (Open)
  • uploadCareId, text
  • URL, text
  • Foreign entity key or use a join table
  • Meta fields: creation, modification, etc

Layouts

Card window

The card window only needs a close button and a webviewer.

Here’s what the card window looks like in browse mode:

File Upload

Drag and Drop any files or choose a local file.

And here it is in layout mode:

File Upload in Layout Mode

Scripts

  1. Button: Calling Script

This script installs an OnTimer script handler that will be specific to the context in which the button is placed.

  1. Handler script

This script will perform any needed actions after the card window is closed.

  1. Reveal card script

This script opens the card window and sets any needed global values.

  1. HandleUpload

This is the workhorse script on the FileMaker side. It is called by the web app and receives a payload that includes these properties:

{

  “state”: “test”,

  “uuid”: “beb37379-5f2d-4ddc-857f-fd2449210958~1”,

  “cdnUrl”: “https://ucarecdn.com/beb37379-5f2d-4ddc-857f-fd2449210958~1/”,

  “name”: “1 file”,

  “count”: 1,

  “size”: 187806,

  “isImage”: true,

  “isStored”: true

}

There are several processes that this script will perform:

  1. The uuid property in the payload received represents the UploadCare group identifier for the batch of files that were uploaded. We can return an array of file objects by sending a GET request to the endpoint that uses the group uuid:

“https://api.uploadcare.com/groups/” & $uuid & “/”

  1. We pass the array of file objects to a batch script that will loop through the array, create the Document records, and store the information we need for each document. 
  2. As each document is created, we also GET and store the thumbnail that UploadCare provides by simply appending “-/preview/200×200/” to the end of the file url. I’ve put the thumbnail specifics in a custom function so that I can edit it easily.
Get thumbnail preview scripts

 

By default, Uploadcare will delete the files uploaded unless you set them to be stored. After successfully creating the couement records in FileMaker, we pass an array of uploadcare uuids to an API that will send a PUT request to Uploadcare’s endpoint to set the file to “stored.”

  1. View Document

This script will download the file and open it. It’s a simple Insert from URL using the file url we stored in the record when it was first created.

View your downloaded script document
  1. Delete Document

When you delete the document record in FileMaker, you should also delete it in Uploadcare. Using the Uploadcare UUID, we send a DELETE request to their file delete endpoint. If that is successful, we delete the FileMaker document record.