.Net Core 5 Web API使用MimeKit、MailKit发送PDF附件损坏问题求助
问题排查结论
1. 服务端SendEmailAsync方法本身无逻辑错误
你编写的邮件附件添加逻辑符合MimeKit规范,读取IFormFile流转字节数组、指定PDF格式的操作都没有问题,附件损坏的核心原因出在前端生成的Blob文件本身就是无效的。
2. 前端错误点
调用doc.output('datauristring')得到的是带前缀的Data URI字符串,格式为data:application/pdf;base64,xxxxxx,直接把这个字符串塞进Blob,相当于把字符串内容当做PDF二进制数据存储,并非真正的PDF字节流,因此传到服务端的文件本身就是损坏的。
修复方案
前端修改(推荐)
把Data URI转成纯二进制字节流再生成Blob,修改对应逻辑即可:
createPdf(): string { var dataURI = doc.output('datauristring'); return dataURI ? dataURI : ""; } // 新增DataURI转二进制Blob方法 dataURItoBlob(dataURI: string): Blob { const byteString = atob(dataURI.split(',')[1]); const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; const ab = new ArrayBuffer(byteString.length); const ia = new Uint8Array(ab); for (let i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ab], { type: mimeString }); } createMail(): void { // 不要直接传入dataURI生成Blob,先转成二进制格式 const pdfBlob = this.dataURItoBlob(this.createPdf()); var fileOfBlob = new File([pdfBlob], this.data.accountName + '_' + this.data.exceptionDate + '_' + 'ExceptionRequest.pdf'); // 后续FormData逻辑无需修改 const mail: FormData = new FormData(); mail.append('ToEmail', this.data.contactEmail); mail.append('Subject', 'Test'); mail.append('Body', 'Test Email'); mail.append('Attachments', fileOfBlob); console.log(fileOfBlob); this.mailService.createMail(mail) .subscribe(res => { console.log(res); }); }
服务端兼容优化(前端无法修改时可选)
如果前端暂时无法迭代,也可以在服务端兼容处理,把收到的文件内容先剔除Data URI前缀再转成二进制:
public async Task SendEmailAsync(MailRequest mailRequest) { var email = new MimeMessage(); email.Sender = MailboxAddress.Parse(_mailSettings.Mail); email.To.Add(MailboxAddress.Parse(mailRequest.ToEmail)); email.Subject = mailRequest.Subject; var builder = new BodyBuilder(); byte[] fileBytes; if (mailRequest.Attachments != null) { var file = mailRequest.Attachments; if (file.Length > 0) { using (var ms = new MemoryStream()) { file.CopyTo(ms); var fileContent = System.Text.Encoding.UTF8.GetString(ms.ToArray()); // 校验是否为Data URI格式,是则截取base64部分转字节 if (fileContent.StartsWith("data:application/pdf;base64,")) { var base64Part = fileContent.Split(',')[1]; fileBytes = Convert.FromBase64String(base64Part); } else { fileBytes = ms.ToArray(); } } builder.Attachments.Add(file.FileName, fileBytes, MimeKit.ContentType.Parse(MediaTypeNames.Application.Pdf)); } } builder.HtmlBody = mailRequest.Body; email.Body = builder.ToMessageBody(); using var smtp = new SmtpClient(); smtp.Connect(_mailSettings.Host, _mailSettings.Port, SecureSocketOptions.StartTls); smtp.Authenticate(_mailSettings.Mail, _mailSettings.Password); await smtp.SendAsync(email); smtp.Disconnect(true); }
内容的提问来源于stack exchange,提问作者fletch413
相关产品推荐
相关产品推荐

