DEV Community

Cover image for How to upload files/images to Netlify Functions
Will
Will

Posted on

How to upload files/images to Netlify Functions

In this post we'll walk through the process of passing an image (or any file) to a Netlify function using FormData and busboy.

Netlify Functions are serverless functions that allow you to run your backend code without managing any infrastructure. They can be used for various tasks, including processing form submissions, handling file uploads, and integrating with other APIs.

FormData is a web API that enables the easy creation and manipulation of form data to be sent as part of an HTTP request.

busboy is what many Express middleware's such as multer use under the hood.

Sending an Image File

To send an image file to the function we'll need a frontend. For demonstration purposes we'll be using a simple React form with a file input and a submit button. We'll use axios for making POST requests to the Netlify function. First, install axios as a dependency:

npm install axios

Now, create an UploadForm.tsx component with the following code:

import { useState, ChangeEvent, FormEvent } from 'react';
import axios from 'axios';

export function UploadForm() {
    const [image, setImage] = useState<File | null>(null);

    function handleChange(e: ChangeEvent<HTMLInputElement>) {
        if (e.target.files) {
            setImage(e.target.files[0]);
        }
    }

    async function handleSubmit(e: FormEvent<HTMLFormElement>) {
        e.preventDefault();

        if (!image) return;

        // Create a FormData object and append the image file
        const formData = new FormData();
        formData.append('image', image);

        // Send the FormData object to the Netlify function
        try {
            const { data } = await axios.post(
                '/.netlify/functions/upload',
                formData,
                {
                    headers: {
                        'Content-Type': 'multipart/form-data',
                    },
                },
            );
            console.log('Upload successful:', data);
        } catch (error) {
            console.error('Upload failed:', error);
        }
    }

    return (
        <form onSubmit={handleSubmit}>
            <input type='file' accept='image/*' onChange={handleChange} />
            <button type='submit'>Upload</button>
        </form>
    );
}
Enter fullscreen mode Exit fullscreen mode

The UploadForm component allows users to select an image file and submit the form. When the form is submitted, it creates a FormData object, appends the selected image, and sends a POST request to the Netlify function.

Configuring the Function & Parsing the Payload

First we'll need to install busboy & @netlify/functions:

npm install busboy
npm install @netlify/functions
npm install --save-dev @types/busboy // If using TypeScript
Enter fullscreen mode Exit fullscreen mode

Now create a new directory named netlify in your project's root directory, then add a folder within there named functions. Inside the netlify/functions directory, create a new file named upload.ts and add the following contents:

import busboy from 'busboy';
import { Handler } from '@netlify/functions';

type Fields = {
    image: {
        filename: string;
        type: string;
        content: Buffer;
    }[];
};

function parseMultipartForm(event): Promise<Fields> {
    return new Promise((resolve) => {
        const fields = { image: [] };
        const bb = busboy({ headers: event.headers });

        bb.on('file', (name, file, info) => {
            const { filename, mimeType } = info;

            file.on('data', (data) => {
                if (!fields[name]) fields[name] = [];

                fields[name].push({
                    filename,
                    type: mimeType,
                    content: data,
                });
            });
        });

        bb.on('close', () => {
            resolve(fields);
        });

        bb.end(Buffer.from(event.body, 'base64'));
    });
}

export const handler: Handler = async (event) => {
    try {
        const fields = await parseMultipartForm(event);

        if (!fields) {
            throw new Error('Unable to parse image');
        }

        console.log('fields is: ', fields);
        console.log('image is: ', fields.image);

        const image = fields.image[0];

        // Handle image however you want here...

        return {
            statusCode: 200,
            body: JSON.stringify(image),
        };
    } catch (error) {
        return {
            statusCode: 400,
            body: error.toString(),
        };
    }
};
Enter fullscreen mode Exit fullscreen mode

To test your changes, run npx netlify dev which will open a local development window. You can then add an image of your choice via the input and hit submit, which should give you something like this in your terminal:

Screenshot of the console log responses

That's it! ✅ You now have an image passed and parsed available to do anything you wish with. You can easily extend this approach to handle other types of file uploads or additional form fields. If you wish to deploy your application simply login to Netlify and connect your Git repository within Netlify and hit "Deploy".

Top comments (0)