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:
And here it is in layout mode:
Scripts
- Button: Calling Script
This script installs an OnTimer script handler that will be specific to the context in which the button is placed.
- Handler script
This script will perform any needed actions after the card window is closed.
- Reveal card script
This script opens the card window and sets any needed global values.
- 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:
- 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 & “/”
- 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.
- 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.
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.”
- 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.
- 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.