
本文详解如何将 HTML 表单中的 文件转换为 Base64 字符串,并通过 JSON POST 请求安全传递给后端,最终以合法格式(string 或 Buffer)注入 Resend emails.send() 的 attachments 字段。
本文详解如何将 html 表单中的 `` 文件转换为 base64 字符串,并通过 json post 请求安全传递给后端,最终以合法格式(`string` 或 `buffer`)注入 resend `emails.send()` 的 `attachments` 字段。
在使用 Resend 发送带附件的邮件时,关键限制在于:Resend 的 attachments[].content 字段仅接受字符串(如 Base64 编码内容)或 Node.js Buffer 对象,而浏览器端的 <input type="file"> 原生返回的是 File 对象(继承自 Blob),无法直接序列化进 JSON 请求体。若错误地尝试 JSON.stringify(files) 或直接传入 File 实例,会导致空数据、类型错误或服务端校验失败(如 "content must be in string or buffer format")。
✅ 正确做法是:在前端用 FileReader 将文件读取为 Data URL(Base64 格式),提取纯 Base64 内容,再通过标准 JSON POST 发送给后端。Data URL 形如 data:application/pdf;base64,xxxxxx...,需去除前缀保留 Base64 主体。
以下是完整实现流程:
1. 前端:读取文件并提取 Base64 内容
const [base64Content, setBase64Content] = useState<string>('');
const [filename, setFilename] = useState<string>('');
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (event) => {
const dataUrl = event.target?.result as string;
// 提取 Base64 主体:移除 'data:*/;base64,' 前缀
const base64String = dataUrl.split(',')[1];
setBase64Content(base64String);
setFilename(file.name);
};
reader.readAsDataURL(file); // ✅ 必须用 readAsDataURL,而非 readAsArrayBuffer(后者不生成 Base64)
};
// 表单中使用
<input
type="file"
accept=".pdf,.jpg,.png,.docx"
onChange={handleFileChange}
/>2. 前端:发送 JSON 请求到后端 API
const sendEmail = async () => {
const res = await fetch('/api/send-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
from: 'Acme <hello@example.com>',
to: ['user@example.com'],
subject: 'With attachment',
text: 'Check the attached file!',
attachments: [{
filename,
content: base64Content, // ✅ 纯 Base64 字符串,可直接用于 Resend
}]
})
});
if (!res.ok) throw new Error('Failed to send email');
};3. 后端(示例:Next.js API Route):构造 Resend 请求
// pages/api/send-email.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY!);
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'POST') return res.status(405).end();
const { from, to, subject, text, attachments } = req.body;
try {
const data = await resend.emails.send({
from,
to,
subject,
text,
attachments: attachments.map((att: any) => ({
filename: att.filename,
content: Buffer.from(att.content, 'base64'), // ✅ 后端转为 Buffer(推荐)或保持字符串
}))
});
res.status(200).json(data);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Email sending failed' });
}
}⚠️ 重要注意事项:
-
不要在前端使用
FormData+fetch直接发给 Resend:Resend 不支持multipart/form-data,且其 SDK 要求content是字符串/Buffer,非File对象。 -
避免
readAsArrayBuffer+JSON.stringify:ArrayBuffer无法直接 JSON 序列化,会变成空对象{}。 -
大文件限制:Resend 单封邮件附件总大小上限为 50MB;Base64 编码会使体积膨胀约 33%,建议前端校验文件大小(
file.size )。 -
安全性:后端务必校验
filename(防止路径遍历)、content是否为有效 Base64(可用正则/^[A-Za-z0-9+/]*={0,2}$/初筛),并设置合理的 MIME 类型白名单。
通过该方案,你既能复用现有 JSON 表单提交架构,又能确保附件内容严格符合 Resend API 规范——简洁、可靠、生产就绪。

















