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
- TypeScript
- JavaScript
const file = await io.input.file("Upload a profile photo", {
helpText: "Select an image.",
allowedExtensions: [".jpg", ".jpeg", ".png"],
});
const file = await io.input.file("Upload a profile photo", {
helpText: "Select an image.",
allowedExtensions: [".jpg", ".jpeg", ".png"],
});
Multiple files
Starting with v0.37.0
, you can also accept multiple files at a time using
the .multiple()
chained method:
- TypeScript
- JavaScript
const file = await io.input
.file("Upload post images", {
helpText: "Select images.",
allowedExtensions: [".jpg", ".jpeg", ".png"],
})
.multiple();
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
- TypeScript
- JavaScript
allowedExtensions
Optional
string[]
disabled
Optional
boolean
generatePresignedUrls
Optional
function
({ name: string, type: string }) => Promise<{
uploadUrl: string,
downloadUrl: string,
}>
helpText
Optional
string
Returns
object
extension
string
lastModified
Date
name
string
size
number
type
string
buffer()
() => Promise<Buffer>
json()
() => Promise<any>
text()
() => Promise<string>
url()
() => Promise<string>
allowedExtensions
Optional
string[]
disabled
Optional
boolean
generatePresignedUrls
Optional
function
({ name: string, type: string }) => Promise<{
uploadUrl: string,
downloadUrl: string,
}>
helpText
Optional
string
Returns
object
extension
string
lastModified
Date
name
string
size
number
type
string
buffer()
() => Promise<Buffer>
json()
() => Promise<any>
text()
() => Promise<string>
url()
() => Promise<string>
Examples
Working with text files
Use the file's .text()
function to obtain its text contents.
- TypeScript
- JavaScript
const file = await io.input.file("Upload a text file", {
allowedExtensions: [".txt", ".md"],
});
// Obtain the file's text contents
const text = await file.text();
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.
- TypeScript
- JavaScript
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();
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.
- TypeScript
- JavaScript
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,
})
);
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:
- TypeScript
- JavaScript
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 });
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": []
}
]