Flutter生成PDF报错:'!_paint' 文档已保存断言异常
Flutter PDF二次生成报错:The document has already been saved 修复方案
问题现象
- 首次触发PDF生成、打开功能可正常运行
- 新增/编辑业务数据后第二次触发生成操作时,输出的PDF文件仍为第一次生成的旧内容,同时抛出未处理异常:
'package:pdf/src/widgets/document.dart': Failed assertion: line 117 pos 12: '!_paint': The document has already been saved
- 现有代码逻辑:
- 按钮点击回调中组装最新的Invoice业务对象,调用
PdfInvoiceApiDsr.generate(invoice)生成PDF,再调用PdfApi.openFile(pdfFile)打开文件 PdfInvoiceApiDsr.dart中在类外部全局定义了final pdf = pw.Document()实例,同时全局定义了依赖该pdf实例的imageA对象;generate静态方法内直接调用该全局pdf实例的addPage方法添加页面时触发报错PdfApi类的saveDocument方法接收文件名、Document类型pdf参数,调用pdf.save()获取字节流后写入应用文档目录,openFile方法调用OpenFile.open打开对应路径文件
- 按钮点击回调中组装最新的Invoice业务对象,调用
问题原因
pdf包的Document对象调用save()方法后,内部_paint标记会被置为true,锁定文档状态,不允许再添加页面、修改内容。全局定义的pdf实例是全局单例,第一次生成时调用save()后实例已经被锁定,第二次生成时复用这个被锁定的实例,既无法添加新页面,之前生成的旧内容也残留在实例中,就会触发断言报错,同时生成的文件还是旧内容。全局绑定旧pdf实例的imageA对象也会复用旧实例的状态,加剧内容异常问题。
修复步骤
- 删除
PdfInvoiceApiDsr.dart类外部全局定义的pw.Document()实例,以及绑定该全局实例的全局imageA对象 - 在
generate静态方法内部,每次调用时都新建一个全新的pw.Document()实例,所有依赖该实例的资源(比如imageA)都在方法内部基于新实例初始化,不做全局复用 - 生成PDF文件名时增加动态标识(比如当前时间戳),同时写入文件前先检查目标路径,若存在旧文件先删除再写入新字节流,避免系统缓存或旧文件残留导致打开时显示旧内容
- 参考修正后的代码逻辑:
// PdfInvoiceApiDsr.dart 修正后generate方法 static Future<File> generate(Invoice invoice) async { // 每次生成都新建全新Document实例 final pdf = pw.Document(); // 所有依赖pdf实例的资源在方法内初始化,和当前实例绑定 final imageA = await _loadInvoiceImage(); // 替换为你原有imageA的初始化逻辑 pdf.addPage( pw.MultiPage( // 原有页面构建逻辑,传入invoice、imageA等参数即可 build: (context) => [ // 发票标题、供应商信息、账单条目、签名等组件 ] ) ); // 文件名加时间戳避免缓存 final outputFileName = 'invoice_${DateTime.now().millisecondsSinceEpoch}.pdf'; return PdfApi.saveDocument(fileName: outputFileName, pdf: pdf); }
// PdfApi.dart saveDocument方法补充旧文件删除逻辑 static Future<File> saveDocument({required String fileName, required pw.Document pdf}) async { final bytes = await pdf.save(); final dir = await getApplicationDocumentsDirectory(); final file = File('${dir.path}/$fileName'); // 存在旧文件先删除 if (await file.exists()) { await file.delete(); } await file.writeAsBytes(bytes); return file; }
内容的提问来源于stack exchange,提问作者LKC
相关产品推荐
相关产品推荐

