Action
File Upload

Example

To upload files on the front end, you can either use a form action or direct call a server action

Form action

// UploadFileViaForm.tsx
'use client';
import { uploadFile } from './file.action';
 
export function UploadFileViaForm() {
	return (
		<form action={uploadFile}>
			{/** The name attribute must match the server action input name */}
			<input type="file" name="file" />
			<button type="submit">Upload via form action</button>
		</form>
	);
}

Direct call

// UploadFileViaActionCall.tsx
'use client';
import { objectToFormData } from '@davstack/action';
import { uploadFile } from './file.action';
 
export default function UploadFileViaActionCall() {
	return (
		<button
			onClick={async () => {
				const file = new Blob([], { type: 'text/plain' });
				// must convert object to form data if using direct call
				await uploadFile(objectToFormData({ file }));
			}}
		>
			upload via direct action call
		</button>
	);
}

When directly calling a server action is is essential to wrap the input in objectToFormData as otherwise next.js will not send the file to the backend.

Backend

// file.action.ts
'use server';
import { action, zodFile } from '@davstack/action';
 
export const uploadFile = action()
	.input({
		file: zodFile({ type: 'image/*' }),
	})
	.mutation(async ({ input, ctx }) => {
		console.log('FILE UPLOADING! ');
		const file = input.file;
	});

Under the hood, davstack action converts formdata to objects so you can use the input as a normal object, no need for formData.get.

zodFile Usage

// Accept only image files
const imageFile = zodFile({ type: 'image/*' });
 
// Accept only audio files
const audioFile = zodFile({ type: 'audio/*' });
 
// Accept only video files
const videoFile = zodFile({ type: 'video/*' });
 
// Accept only PDF files
const pdfFile = zodFile({ type: 'application/pdf' });
 
// Accept only text files
const textFile = zodFile({ type: 'text/*' });
 
// Accept specific file types
const specificTypes = zodFile({ type: ['image/jpeg', 'image/png'] });
 
// Accept custom file type
const customType = zodFile({ type: 'application/custom' });
 
// Set maximum file size (in bytes)
const limitedSize = zodFile({ type: '*', maxSizeMb: 5 });

The zodFile validator allows you to specify the expected file type and maximum size:

  • Use type: 'image/*', type: 'audio/*', type: 'video/*', etc., to accept files of a specific category.
  • Use type: 'application/pdf', type: 'text/*', etc., to accept files of a specific type.
  • Use an array of types, like type: ['image/jpeg', 'image/png'], to accept multiple specific types.
  • Use a custom type string, like type: 'application/custom', to accept a custom file type.

The zodFile validator returns a ZodFile object with properties and methods for working with the uploaded file.