I highly recommend using the popular and lightweight formidable
library:
# installation steps
yarn add formidable@v3 @types/formidable
// file-upload.ts
import fs from "fs";
import path from "path";
import { File } from "formidable";
// Important for NextJS!
export const config = {
api: {
bodyParser: false,
},
};
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<string>
) {
try {
// Parse request using formidable
const { fields, files } = await parseFormAsync(req);
// Files are now in arrays (since formidable v3+)
const myfile = (files["myfile"] as any as File[])[0];
// Save uploaded file in the public folder
saveFile(myfile, "./public/uploads");
// Return success message
res.status(200).json("success!");
} catch (e) {
return res.status(500).json(e);
}
}
function saveFile(file: File, publicFolder: string): void {
const fileExt = path.extname(file.originalFilename || "");
fs.renameSync(file.filepath, `${publicFolder}/${file.newFilename}${fileExt}`);
}
// ./helpers/formidable.ts
import type { NextApiRequest } from "next";
import formidable from "formidable";
export type FormidableParseReturn = {
fields: formidable.Fields;
files: formidable.Files;
};
export async function parseFormAsync(
req: NextApiRequest,
formidableOptions?: formidable.Options
): Promise<FormidableParseReturn> {
const form = formidable(formidableOptions);
return await new Promise<FormidableParseReturn>((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
reject(err);
}
resolve({ fields, files });
});
});
}
Bonus question
Here's a bonus question - it might not be secure to store uploaded images in a public folder. Consider storing them on the cloud instead.
Using S3 and other cloud services
You can integrate with various cloud services using Formidable.
Check out official examples here: https://github.com/node-formidable/formidable/blob/master/examples/store-files-on-s3.js
However, if you prefer local storage for private uploads, that's also an option.
Managing private uploads locally
- Saving:
- Accessing:
- Create an API endpoint to retrieve the file
- Example:
https://.../uploads/{filename}
- Ensure only authenticated user can access their files;
- Send the file as response;
- Security Measures:
- Be cautious about hackers attempting unauthorized access using techniques like
..
in the filename
;
- Sanitize filenames by restricting to alphanumeric characters;
- Alternatively, use a database table for ownership control rather than directory structure;