You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter PDF包iOS端TooManyPagesException异常求助

Flutter pdf包iOS端生成PDF时出现TooManyPagesException异常(Android正常)

问题详情

在使用pdf包生成PDF时,仅iOS端出现异常,Android端运行正常:

  1. 初始问题:Widget高度(823.408)超过页面高度(728.5039370078739),提示需使用SpanningWidget或单页布局;
  2. 改用Wrap组件(SpanningWidget的一种)包裹内容后,抛出新的异常,错误栈如下:

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Instance of 'TooManyPagesException' #0 MultiPage.generate (package:pdf/src/widgets/multi_page.dart:251:9) #1 Document.addPage (package:pdf/src/widgets/document.dart:117:10) #2 _QuillPageState.generatePdf (package:daiaryapp/pages/addDairyPage/quill_page.dart:76:9) #3 _QuillPageState.build.. (package:daiaryapp/pages/addDairyPage/quill_page.dart:320:48)

相关代码:

pdf.addPage(pw.MultiPage(
      build: (pw.Context context) {
        final content = <pw.Widget>[];

        content.add(
          pw.Center(
            child: pw.Text(
              post.dairyName.toString(), // Replace with your desired title
              style: customTitle,
            ),
          ),
        );

        int itemsPerPage = 8;

        for (var i = 0; i < deltaData['ops'].length; i++) {
          final op = deltaData['ops'][i];

          if (op.containsKey('insert')) {
            if (op['insert'] is String) {
              final lines = (op['insert'] as String).split('-');

              for (var line in lines) {
                final textWidget = pw.Padding(
                  padding: pw.EdgeInsets.all(1.0),
                  child: pw.Text(
                    line.trim(), // Trim to remove extra spaces
                    style: customTextStyle, // Apply custom text style here
                  ),
                );

                content.add(textWidget);
              }
            } else if (op['insert'] is Map &&
                op['insert'].containsKey('image')) {
              final imageData = op['insert']['image'].split(',')[1];
              final Uint8List decodedImage = base64Decode(imageData);

              final imageWidget = pw.Padding(
                padding: pw.EdgeInsets.all(1.0),
                child: pw.Image(
                  pw.MemoryImage(
                    decodedImage,
                  ),
                  fit: pw.BoxFit.cover,
                  height: 245.0,
                ),
              );

              content.add(imageWidget);
            }
          }

          if (i > 0 && (i + 1) % itemsPerPage == 0) {
            content.add(pw.Container(width: 1.0, height: 1.0));
          }
        }

        // return content;
        return [
          pw.Wrap(
            children: content,
          ),
        ];
      },
    ));

解决方案

方案1:移除Wrap,利用MultiPage自动分页能力

Wrap组件会打乱MultiPage的分页逻辑,导致无法合理拆分内容,直接返回内容列表即可:

  1. 取消Wrap包裹,直接返回content;
  2. 移除手动添加的空Container,避免干扰分页计算;
  3. 图片不要固定高度,改为根据页面宽度自适应,避免单页高度溢出:
pw.Image(
  pw.MemoryImage(decodedImage),
  fit: pw.BoxFit.fitWidth,
  width: context.pageFormat.availableWidth,
)

方案2:显式指定页面格式并设置分页上限

iOS端默认页面格式可能与Android存在差异,同时设置maxPages避免无限分页:

pdf.addPage(pw.MultiPage(
  pageFormat: pw.PageFormat.a4, // 统一使用A4尺寸
  maxPages: 100, // 根据业务需求设置合理上限
  build: (pw.Context context) {
    // 原有内容逻辑...
    return content;
  },
));

方案3:改用SinglePage(业务允许单页展示时)

如果业务不需要分页,可使用SinglePage并开启裁剪处理溢出内容:

pdf.addPage(pw.SinglePage(
  clip: true,
  build: (pw.Context context) {
    // 原有内容逻辑...
    return pw.Column(children: content);
  },
));

总结

优先尝试方案1,移除Wrap和空Container,让MultiPage自动处理分页,同时自适应图片尺寸,这是解决此类跨端分页异常最直接的方式。若仍有问题,再通过调整页面格式或分页上限进一步排查。

内容的提问来源于stack exchange,提问作者Muhammad Naseer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 18:01:24