React Native中ArrayBuffer创建Blob报错:HTML转PDF含签名导出求助
解决Expo React Native中Blob创建报错(ArrayBuffer不支持)的问题
问题原因
Expo环境下的Blob实现与Web端存在差异,原生不支持通过ArrayBuffer或ArrayBufferView创建Blob,这就是你在dataURItoBlob函数中触发Error: Creating blobs from 'ArrayBuffer' and 'ArrayBufferView' are not supported.的核心原因。
解决方案
以下是两种可行的修复方案,优先推荐方案2,更贴合Expo生态且兼容性更强:
方案1:修改dataURItoBlob函数,用fetch转换dataURI为Blob
利用fetch API处理data URI,生成Expo兼容的Blob对象:
async function dataURItoBlob(dataURI) { const response = await fetch(dataURI); return response.blob(); } // 在handleSubmit中调用 async function handleSubmit() { const htmlContent = getHtmlWithSignature(); // 你的HTML获取逻辑 const pdfDataURI = await htmlToPdf.convert(htmlContent); // 假设你使用的HTML转PDF库 try { const blob = await dataURItoBlob(pdfDataURI); // 构建FormData上传Blob到后端 const formData = new FormData(); formData.append('pdf', blob, 'signed-document.pdf'); await fetch('your-backend-api/upload-pdf', { method: 'POST', body: formData, }); } catch (err) { console.error('处理PDF失败:', err); } }
方案2:直接传递base64字符串给后端处理(推荐)
跳过前端生成Blob的步骤,将PDF的base64字符串传给ASP.NET Core后端,由后端负责生成文件并发送邮件,彻底规避Expo的Blob兼容问题:
前端代码(Expo)
import * as Print from 'expo-print'; import * as FileSystem from 'expo-file-system'; async function handleSubmit() { const htmlContent = getHtmlWithSignature(); // 用Expo官方库生成标准尺寸PDF const { uri } = await Print.printToFileAsync({ html: htmlContent, width: 612, // 72dpi下8.5英寸标准宽度 height: 792, // 72dpi下11英寸标准高度 }); // 将PDF文件读取为base64字符串 const pdfBase64 = await FileSystem.readAsStringAsync(uri, { encoding: FileSystem.EncodingType.Base64, }); // 发送到后端API try { await fetch('your-backend-api/send-pdf-email', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ pdfBase64: pdfBase64, customerEmail: 'customer@example.com', // 替换为实际客户邮箱 subject: '您的签名文档', body: '请查收附件中的签名文档' }), }); alert('邮件已发送'); } catch (err) { console.error('发送失败:', err); alert('发送失败,请重试'); } }
后端ASP.NET Core 8代码
using Microsoft.AspNetCore.Mvc; using MimeKit; using MailKit.Net.Smtp; [ApiController] [Route("api/[controller]")] public class PdfEmailController : ControllerBase { [HttpPost("send")] public async Task<IActionResult> SendPdfEmail([FromBody] PdfEmailRequest request) { if (string.IsNullOrEmpty(request.PdfBase64) || string.IsNullOrEmpty(request.CustomerEmail)) { return BadRequest("缺少必要参数"); } try { // 将base64转为字节数组 byte[] pdfBytes = Convert.FromBase64String(request.PdfBase64); // 构建邮件内容 var message = new MimeMessage(); message.From.Add(new MailboxAddress("你的应用名称", "your-app-email@example.com")); message.To.Add(new MailboxAddress("客户", request.CustomerEmail)); message.Subject = request.Subject ?? "您的签名文档"; var bodyBuilder = new BodyBuilder(); bodyBuilder.TextBody = request.Body ?? "请查收附件中的签名文档"; // 添加PDF附件 bodyBuilder.Attachments.Add("signed-document.pdf", pdfBytes, ContentType.Parse("application/pdf")); message.Body = bodyBuilder.ToMessageBody(); // 发送邮件(替换为你的SMTP配置) using var client = new SmtpClient(); await client.ConnectAsync("smtp.example.com", 587, MailKit.Security.SecureSocketOptions.StartTls); await client.AuthenticateAsync("smtp-username", "smtp-password"); await client.SendAsync(message); await client.DisconnectAsync(true); return Ok(new { success = true, message = "邮件发送成功" }); } catch (Exception ex) { return StatusCode(500, new { success = false, message = $"发送失败: {ex.Message}" }); } } } // 请求模型 public class PdfEmailRequest { public string PdfBase64 { get; set; } public string CustomerEmail { get; set; } public string Subject { get; set; } public string Body { get; set; } }
依赖检查
如果使用方案2,确保package.json中包含以下Expo官方依赖:
{ "dependencies": { "expo-print": "~12.8.1", "expo-file-system": "~16.0.8", // 其他项目依赖... } }
内容的提问来源于stack exchange,提问作者Marco Chitu
相关产品推荐
相关产品推荐

