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

Flutter应用使用PDF渲染库无法显示PNG签章问题

Flutter PDF签名应用渲染签章问题

问题描述

我开发了一款用于PDF签名的Flutter应用,目前存在一处bug:应用使用PNG图片(Web端和Flutter端均适用)进行签名,上传后PDF无法显示签章。但查看模拟器缓存发现,下载的PDF文件本身是带有签章的,推测问题出在渲染环节。

下载PDF的代码片段

import 'dart:ui';

import 'package:bloc/bloc.dart';
import 'package:flutter/foundation.dart';
import 'package:martidocs/util/app_config.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:pdf_render/pdf_render.dart';

void parsePdf({required String filename}) async {
    emit(DigitalSignatureLoading());
    try {
      List<Image> images = [];
      final pdfFile = await DefaultCacheManager()
          .getSingleFile('${AppConfig.currentUrl}file/get/$filename');
      final buffer = await pdfFile.readAsBytes();
      final document = await PdfDocument.openData(buffer);

      for (var i = 1; i <= document.pageCount; i++) {
        final page = await document.getPage(i);
        final pageImage = await page.render(
            width: page.width.toInt(), height: page.height.toInt());
        final image = await pageImage.createImageIfNotAvailable();
        images.add(image);
      }

      emit(DigitalSignaturePDFParseLoaded(images: images));
    } catch (e) {
      emit(DigitalSignatureFail());
    }
  }

展示PDF的代码片段

List<DigitalSignaturePlacementResponse> placements = [];
  List<UI.Image> pages = [];

  int totalPage = 0;
  int currentPage = 1;

@override
  void initState() {
    super.initState();
    _cubit = BlocProvider.of<DigitalSignatureCubit>(context);
    _cubit.parsePdf(filename: widget.digitalSignature.documentUrl ?? '');
  }

body: BlocConsumer<DigitalSignatureCubit, DigitalSignatureState>(
        listener: (context, state) {
          if (state is DigitalSignaturePDFParseLoaded) {
            totalPage = state.images.length;
            pages = state.images;
          } .....

// 无需关注placement逻辑,已签名时会正常显示
Widget previewFileWidget() => SizedBox(
        height: MediaQuery.of(context).size.height * 0.65,
        child: PageView.builder(
            itemCount: pages.length,
            pageSnapping: true,
            onPageChanged: (value) {
              setState(() {
                currentPage = value + 1;
              });
            },
            itemBuilder: (context, pagePosition) {
              final pagePlacements = placements
                  .where((element) => element.page == pagePosition)
                  .toList();
              var stackChild = [
                Positioned.fill(
                    child: RawImage(
                  key: containerGlobalKey,
                  fit: BoxFit.fitHeight,
                  image: pages[pagePosition],
                  alignment: Alignment.topCenter,
                )),
              ];

              for (var i = 0; i < pagePlacements.length; i++) {
                final x = (pagePlacements[i].xPlace / 100) *
                    MediaQuery.of(context).size.width;
                final y = ((100 - pagePlacements[i].yPlace) / 100) *
                    (MediaQuery.of(context).size.height * 0.65);
                stackChild.add(Positioned(
                    top: y - 10,
                    left: x,
                    child: Container(
                      decoration: BoxDecoration(
                          image: DecorationImage(
                              image:
                                  AssetImage(imagePath('placeholder-sign')))),
                      width: 400 * (pagePlacements[i].size / 100),
                      height: 62 * (pagePlacements[i].size / 100),
                      child: Center(
                        child: Text(
                          pagePlacements[i].username,
                          style: MartidocsTheme.plainText.copyWith(fontSize: 9),
                        ),
                      ),
                    )));
              }
              return InteractiveViewer(
                  panEnabled: false, // Set it to false
                  boundaryMargin: const EdgeInsets.all(100),
                  minScale: 0.5,
                  maxScale: 2,
                  child: Stack(
                    children: stackChild,
                  ));
            }),
      );

尝试过的方案

  • 最初使用已废弃的pdf_render库,发现问题后更换为替代库pdfrx,但问题依旧存在。

示例说明

  • 未上传签章的示例PDF:显示无签章的空白PDF页面
  • 带有PNG签章的上传数据示例:显示包含PNG签章信息的上传数据界面
  • 渲染结果:文本正常显示,但签章图片未显示:PDF中的文本内容正常渲染,但签章图片完全缺失

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 19:37:25