I’m creating a contact form with Next.js that works with AWS S3 for file uploads and Mailgun for email notifications. The form includes standard input fields along with an option to upload files.
The intended process is: a user picks a file → it uploads to S3 → the generated S3 link is included in an email → the email is sent through Mailgun.
However, I’m facing a problem where the uploaded files are showing up as empty in the S3 bucket. Although the files’ names seem correct and I receive emails with those names, all files appear blank regardless of their type (like images or documents).
uploadFile.ts (API route)
const awsS3 = new S3({
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY,
signatureVersion: 'v4',
});
export const config = {
api: {
bodyParser: {
sizeLimit: '10mb',
},
},
};
export default async (request: NextApiRequest, response: NextApiResponse) => {
if (request.method !== 'POST') {
return response.status(405).json({ error: 'Method not allowed' });
}
try {
let { fileName, fileType } = request.body;
let uploadParams = {
Bucket: process.env.S3_BUCKET_NAME,
Key: fileName,
Expires: 600,
ContentType: fileType,
ACL: 'public-read',
};
const signedUrl = await awsS3.getSignedUrlPromise('putObject', uploadParams);
response.status(200).json({ signedUrl });
} catch (error) {
console.log(error);
response.status(400).json({ error: error });
}
};
File handling function
const onFileSelect = async (e: any) => {
e.preventDefault();
e.stopPropagation();
setSelectedFile(e.target.files[0]);
setFileName(e.target.files[0].name);
setFileType(e.target.files[0].type);
setS3FileUrl(BUCKET_BASE_URL + e.target.files[0].name);
let { data } = await axios.post('/api/fileUpload', {
fileName: e.target.files[0].name,
fileType: e.target.files[0].type,
});
const uploadUrl = data.signedUrl;
await axios.put(uploadUrl, selectedFile, {
headers: {
'Content-Type': e.target.files[0].type,
},
});
setSelectedFile(null);
};
Form submit function
const onFormSubmit = async (event: any) => {
event.preventDefault();
const payload = {
userEmail: email,
userName: fullName,
messageSubject: subject,
messageBody: messageText,
attachmentUrl: s3FileUrl
};
await fetch('/api/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
};
It looks like the files are actually being uploaded to S3, but they end up being empty. I’m trying to figure out what might be causing this problem.