I’m working on a contact form using Next.js that uploads files to AWS S3 and sends emails via Mailgun. The form has regular input fields plus file upload functionality. When someone uploads a file, it should go to S3 first, then the S3 URL gets attached to the email. Everything seems to work but the uploaded files are completely empty. The file names are correct in both the S3 bucket and email attachments, but whether it’s an image, PDF, or text file, they all have zero content.
s3Upload.ts (api route)
const awsS3 = new AWS.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 (req, res) => {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { fileName, fileType } = req.body;
const uploadParams = {
Bucket: process.env.S3_BUCKET_NAME,
Key: fileName,
Expires: 600,
ContentType: fileType,
ACL: 'public-read',
};
const signedUrl = await awsS3.getSignedUrlPromise('putObject', uploadParams);
res.status(200).json({ signedUrl });
} catch (error) {
console.log(error);
res.status(400).json({ error: error.message });
}
};
File upload handler
const onFileChange = async (e) => {
e.preventDefault();
e.stopPropagation();
const selectedFile = e.target.files[0];
setCurrentFile(selectedFile);
setCurrentFileName(selectedFile.name);
setCurrentFileType(selectedFile.type);
setS3FileUrl(S3_BUCKET_URL + selectedFile.name);
const response = await axios.post('/api/s3Upload', {
fileName: selectedFile.name,
fileType: selectedFile.type,
});
const uploadUrl = response.data.signedUrl;
await axios.put(uploadUrl, currentFile, {
headers: {
'Content-Type': selectedFile.type,
},
});
setCurrentFile(null);
};
Form submission handler
const onFormSubmit = async (event) => {
event.preventDefault();
const formPayload = {
senderName: userName,
emailSubject: userSubject,
senderEmail: userEmail,
messageContent: userMessage,
attachmentUrl: s3FileUrl
};
await fetch('/api/sendEmail', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formPayload),
});
};
The files appear in S3 with correct names but zero bytes. Any ideas what could be causing this issue?