Skip to main content
Big news! Interval has been acquired by Meter. Learn more →

io.input.file

Prompts the app user to select and upload a file.

The resulting object points to a temporary file that expires after the action finishes running. You can access its contents in your action and optionally persist the file elsewhere if it should live longer.

Beginning with SDK v0.24.0, you may upload the file directly to your own S3-compatible API by providing custom presigned upload and download URLs.

caution

The resulting temporary file expires after the action finishes running. Please persist the file elsewhere if it should live longer, or provide a custom presigned upload URL.

Usage

const file = await io.input.file("Upload a profile photo", {
helpText: "Select an image.",
allowedExtensions: [".jpg", ".jpeg", ".png"],
});
interval.com

Multiple files

Starting with v0.37.0, you can also accept multiple files at a time using the .multiple() chained method:

const file = await io.input
.file("Upload post images", {
helpText: "Select images.",
allowedExtensions: [".jpg", ".jpeg", ".png"],
})
.multiple();

Note that the above still requires at least one file to be provided. To accept zero or more files, use .multiple().optional().

Props

allowedExtensions

Optional

string[]

Array of file extensions accepted by the file input.

disabled

Optional

boolean

Whether the input is disabled, preventing file uploads.

generatePresignedUrls

Optional

function

Optional function that generates presigned URLs for uploading and downloading files. Works with any S3-compatible API. Available beginning with SDK v0.24.0.
({ name: string, type: string }) => Promise<{
uploadUrl: string,
downloadUrl: string,
}>

helpText

Optional

string

Secondary label providing additional context for the file. Supports inline markdown elements like bold, italics, and links.

Returns

object

extension

string

The file's extension. An empty string if the file name does not have one.

lastModified

Date

A JavaScript Date object representing the modification date of the file.

name

string

The name of the file.

size

number

The size of the file in bytes.

type

string

The MIME type of the file.

buffer()

() => Promise<Buffer>

An asynchronous function returning the file's contents as a Buffer object.

json()

() => Promise<any>

An asynchronous fallible function returning the file's contents as a deserialized object. Can fail if file is not valid JSON.

text()

() => Promise<string>

An asynchronous fallible function returning the file's contents as a string. Can fail if file cannot be serialized to a string.

url()

() => Promise<string>

An asynchronous function returning a temporary presigned URL to the file.

Examples

Working with text files

Use the file's .text() function to obtain its text contents.

const file = await io.input.file("Upload a text file", {
allowedExtensions: [".txt", ".md"],
});

// Obtain the file's text contents
const text = await file.text();

Working with JSON files

If you are working with JSON files, the file's .json() function will handle deserialization for you.

const file = await io.input.file("Upload a saved configuration file", {
allowedExtensions: [".json"],
});

// Obtain the file's contents and parse it as JSON
const config = await file.json();
info

This can throw an error if the file does not contain valid JSON.

Consider wrapping calls to .json() in a try...catch block if you want to handle the error.

Working with binary files

To obtain the raw binary data of the file, for example if you're working with images or video, use the file's .buffer() function.

const file = await io.input.file("Upload a profile photo", {
allowedExtensions: [".jpg", ".jpeg", ".png"],
});

// Obtain the file's contents as a binary Buffer
const buffer = await file.buffer();

// Save the image contents locally to disk
fs.writeFileSync(`/path/to/file/${image.name}`, buffer);

// Or, upload to S3 (or another file hosting provider)
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

const s3 = new S3Client({ region: "us-west-1" });
await s3.send(
new PutObjectCommand({
Bucket: process.env.S3_BUCKET_NAME,
Key: file.name,
Body: buffer,
})
);

Uploading to your own S3 bucket

You can upload files directly to any S3-compatible storage by providing custom upload and download URLs in an optional generatePresignedUrls() handler:

import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const file = await io.input.file("Upload a profile photo", {
allowedExtensions: [".jpg", ".jpeg", ".png"],
generatePresignedUrls: async ({ name }) => {
const path = `profile-photos/${new Date().getTime()}-${name}`;

const s3Client = new S3Client({
region: process.env.AWS_REGION,
credentials: {
accessKeyId: process.env.AWS_KEY_ID,
secretAccessKey: process.env.AWS_KEY_SECRET,
},
});

const putCommand = new PutObjectCommand({
Bucket: process.env.AWS_S3_BUCKET,
Key: path,
});

const uploadUrl = await getSignedUrl(s3Client, putCommand, {
expiresIn: 3600,
});

// The download URL does not need to be presigned
// if your bucket settings allow public access
const url = new URL(uploadUrl);
const downloadUrl = url.origin + url.pathname;

return { uploadUrl, downloadUrl };
},
});

const avatarUrl = await file.url();

await updateUser(userId, { avatarUrl });

In order for the upload to be accepted, your S3 bucket's cross-origin resource sharing (CORS) settings must allow PUT requests:

// Example S3 cross-origin resource sharing (CORS) config:
[
{
"AllowedHeaders": [
"Content-Type"
],
"AllowedMethods": [
"PUT",
"GET"
],
"AllowedOrigins": [
"https://interval.com"
],
"ExposeHeaders": []
}
]
Was this section useful?