如何通过Minio预签名URL获取PDF并直接用Nodemailer发送(不落地)
解决方案:直接通过流将Minio预签名URL的PDF作为Nodemailer附件发送
你不需要把文件保存到本地,Nodemailer支持直接用流对象作为附件内容,只要把HTTP请求拿到的响应流直接传给附件配置就行,完全跳过本地文件写入的步骤。
核心思路
用https.get请求预签名URL获取文件流,把这个响应流直接赋值给Nodemailer附件的content字段,Nodemailer会自动读取流内容并作为附件发送。
基础实现代码
const https = require('https'); const nodemailer = require('nodemailer'); // 初始化Nodemailer传输器(根据你的邮箱服务商配置) const transporter = nodemailer.createTransport({ service: 'Gmail', // 也可以替换成其他SMTP服务,比如QQ邮箱 auth: { user: '你的邮箱地址', pass: '邮箱授权码或登录密码' } }); // 请求Minio预签名URL获取PDF流 https.get(signedUrl, (res) => { // 检查请求是否成功 if (res.statusCode !== 200) { console.error(`获取PDF失败,状态码:${res.statusCode}`); res.resume(); // 释放未使用的响应流资源 return; } // 配置邮件参数 const mailOptions = { from: '发件人邮箱 <sender@example.com>', to: '收件人邮箱 <recipient@example.com>', subject: '包含PDF附件的邮件', text: '请查看附件中的PDF文件', attachments: [ { filename: 'sample.pdf', // 收件人看到的附件名称 content: res, // 直接传入HTTP响应流 contentType: 'application/pdf' // 指定文件MIME类型,确保客户端正确识别 } ] }; // 发送邮件 transporter.sendMail(mailOptions, (error, info) => { if (error) { return console.error('邮件发送失败:', error); } console.log('邮件发送成功:', info.response); }); }).on('error', (err) => { console.error('请求预签名URL出错:', err); });
进阶:用Async/Await优化异步流程
如果习惯用异步语法,可把流获取和邮件发送封装成Promise,让代码逻辑更清晰:
const https = require('https'); const nodemailer = require('nodemailer'); async function sendPdfByEmail(signedUrl) { try { // 初始化传输器 const transporter = nodemailer.createTransport({ service: 'Gmail', auth: { user: '你的邮箱', pass: '授权码' } }); // 获取PDF流的Promise封装 const getPdfStream = () => new Promise((resolve, reject) => { https.get(signedUrl, (res) => { if (res.statusCode !== 200) { reject(new Error(`获取PDF失败:状态码${res.statusCode}`)); res.resume(); return; } resolve(res); }).on('error', reject); }); const pdfStream = await getPdfStream(); // 发送邮件 await transporter.sendMail({ from: '发件人 <sender@example.com>', to: '收件人 <recipient@example.com>', subject: 'PDF附件邮件', text: '附件为Minio存储的PDF文件', attachments: [ { filename: 'sample.pdf', content: pdfStream, contentType: 'application/pdf' } ] }); console.log('邮件发送成功'); } catch (err) { console.error('处理失败:', err); } } // 调用函数 sendPdfByEmail(signedUrl);
关键注意点
- 彻底舍弃
fs.createWriteStream,直接复用HTTP响应流即可 - 必须指定
contentType为application/pdf,避免邮件客户端无法识别附件类型 - 要处理HTTP请求和邮件发送过程中的错误,防止资源泄漏
内容的提问来源于stack exchange,提问作者Uma
相关产品推荐
相关产品推荐

