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

Flutter中Generate PDF按钮失效,MemoryImage引发索引越界错误

问题

开发Flutter应用时,使用package:pdf/pdf.dart包实现点击按钮生成PDF功能,但"Generate PDF"按钮无法正常工作,控制台抛出如下错误:

E/flutter ( 7975): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)]
Unhandled Exception: RangeError (index): Index out of range: no indices are valid: 0 E/flutter ( 7975): #0 Uint8List.[]
(dart:typed_data-patch/typed_data_patch.dart:2271:7) E/flutter (
7975): #1 InputBuffer.[]
(package:image/src/util/input_buffer.dart:44:39) E/flutter ( 7975): #2
JpegData.validate
(package:image/src/formats/jpeg/jpeg_data.dart:64:17) E/flutter (
7975): #3 JpegDecoder.isValidFile
(package:image/src/formats/jpeg_decoder.dart:18:50) E/flutter ( 7975):
#4 findDecoderForData (package:image/src/formats/formats.dart:116:11) E/flutter ( 7975): #5
new MemoryImage (package:pdf/src/widgets/image_provider.dart:101:24)
E/flutter ( 7975): #6 CetakinvoicePage._generatePDF. (package:smta/cetakinvoicepage.dart:421:22) E/flutter (
7975): #7 Page.postProcess
(package:pdf/src/widgets/page.dart:142:21) E/flutter ( 7975): #8
Document.save (package:pdf/src/widgets/document.dart:130:14) E/flutter
( 7975): #9 CetakinvoicePage._generatePDF
(package:smta/cetakinvoicepage.dart:442:39) E/flutter ( 7975):
E/flutter ( 7975):

相关代码如下:

import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:path_provider/path_provider.dart';
import 'package:open_file/open_file.dart';
import 'package:flutter/services.dart' show rootBundle;

class CetakinvoicePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: SingleChildScrollView(
            child: Column(
              children: [
                // Your existing content here...
                Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Padding(
                        padding: EdgeInsets.symmetric(horizontal: 20.0),
                        child: Column(
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: [
                              SizedBox(height: 10.0,),
                              Padding(
                                padding: EdgeInsets.symmetric(horizontal: 10.0),
                                child: Row(
                                  children: [
                                    Image.asset(
                                      'assets/images/logosgntulisan.png',
                                      width: 120,
                                    ),
                                    Spacer(),
                                    Column(
                                      children: [
                                        Image.asset(
                                          'assets/images/barcodedummy.png',
                                          width: 150,
                                        ),
                                        SizedBox(height: 5.0,),
                                        const Text(
                                          'SG10202312060001',
                                          style: TextStyle(
                                            fontSize: 16,
                                            color: Colors.black,
                                            fontWeight: FontWeight.w400,
                                          ),
                                        ),
                                      ],
                                    ),
                                  ],
                                ),
                              ),
                              Padding(
                                padding: EdgeInsets.symmetric(horizontal: 5.0),
                                child: Container(
                                  width: double.infinity,
                                  child: const Divider(
                                    color: Colors.black,
                                    thickness: 1.0,
                                  ),
                                ),
                              ),
                              Column(
                                children: [
                                  const Text(
                                    'PT SINERGI GULA NUSANTARA',
                                    style: TextStyle(
                                      fontSize: 16,
                                      color: Colors.black,
                                      fontWeight: FontWeight.w500,
                                    ),
                                  ),
                                ],
                              ),
                            ]
                        ),
                      ),
                    ]
                ),
                // Button to trigger PDF generation
                SizedBox(height: 10.0,),
                ElevatedButton(
                  onPressed: () {
                    _generatePDF(context);
                  },
                  child: Text('Generate PDF'),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  // Function to generate PDF
  Future<void> _generatePDF(BuildContext context) async {
    final pdf = pw.Document();


    // Add content to the PDF
    pdf.addPage(pw.Page(
      pageFormat: PdfPageFormat.a4,
      build: (pw.Context context) {
        return pw.Row(
          children: [
            pw.Column(
              crossAxisAlignment: pw.CrossAxisAlignment.start,
              children: [
              ],
            ),
            pw.Column(
              crossAxisAlignment: pw.CrossAxisAlignment.start,
              mainAxisAlignment: pw.MainAxisAlignment.end,
              children: [
                pw.Text(
                  'Waktu Masuk',
                  style: pw.TextStyle(
                    fontSize: 14,
                    color: PdfColors.black,
                    fontWeight: pw.FontWeight.bold,
                  ),
                ),
                pw.SizedBox(height: 5.0),
                pw.Text(
                  '14-12/2023 19.00',
                  style: pw.TextStyle(
                    fontSize: 14,
                    color: PdfColors.black,
                    fontWeight: pw.FontWeight.normal,
                  ),
                ),
                pw.SizedBox(height: 10.0),
                pw.Image(
                  pw.MemoryImage(
                    // Convert your image to bytes (you might need to change this part)
                    // For example: (await rootBundle.load('assets/images/truktebugambar.jpg')).buffer.asUint8List()
                    Uint8List.fromList([/* your image bytes go here */]),
                  ),
                  height: 100,
                  width: 120,
                ),
                pw.SizedBox(height: 20.0),
              ],
            ),
          ],
        );
      },
    ));

    // Get the application documents directory
    final directory = await getApplicationDocumentsDirectory();

    // Create the PDF file
    final file = File('${directory.path}/example.pdf');
    await file.writeAsBytes(await pdf.save());

    // Open the PDF using a PDF viewer
    OpenFile.open(file.path);
  }
}

解决方案

错误根源在于pw.MemoryImage传入了空的Uint8List,导致图片解码器无法处理无效数据,抛出索引越界错误。按以下步骤修复:

  • 导入缺失依赖:代码中使用File但未导入dart:io,需在文件顶部添加:

    import 'dart:io';
    
  • 加载实际图片字节:在生成PDF前,通过rootBundle异步加载assets中的图片,转换为Uint8List后传入pw.MemoryImage。修改后的_generatePDF函数如下:

    Future<void> _generatePDF(BuildContext context) async {
      final pdf = pw.Document();
    
      // 异步加载assets中的图片字节
      final imageBytes = (await rootBundle.load('assets/images/truktebugambar.jpg')).buffer.asUint8List();
    
      pdf.addPage(pw.Page(
        pageFormat: PdfPageFormat.a4,
        build: (pw.Context context) {
          return pw.Row(
            children: [
              pw.Column(
                crossAxisAlignment: pw.CrossAxisAlignment.start,
                children: [],
              ),
              pw.Column(
                crossAxisAlignment: pw.CrossAxisAlignment.start,
                mainAxisAlignment: pw.MainAxisAlignment.end,
                children: [
                  pw.Text(
                    'Waktu Masuk',
                    style: pw.TextStyle(
                      fontSize: 14,
                      color: PdfColors.black,
                      fontWeight: pw.FontWeight.bold,
                    ),
                  ),
                  pw.SizedBox(height: 5.0),
                  pw.Text(
                    '14-12/2023 19.00',
                    style: pw.TextStyle(
                      fontSize: 14,
                      color: PdfColors.black,
                      fontWeight: pw.FontWeight.normal,
                    ),
                  ),
                  pw.SizedBox(height: 10.0),
                  pw.Image(
                    pw.MemoryImage(imageBytes),
                    height: 100,
                    width: 120,
                  ),
                  pw.SizedBox(height: 20.0),
                ],
              ),
            ],
          );
        },
      ));
    
      final directory = await getApplicationDocumentsDirectory();
      final file = File('${directory.path}/example.pdf');
      await file.writeAsBytes(await pdf.save());
    
      OpenFile.open(file.path);
    }
    
  • 验证assets配置:确保pubspec.yaml中已正确声明图片资源,例如:

    flutter:
      assets:
        - assets/images/truktebugambar.jpg
        - assets/images/logosgntulisan.png
        - assets/images/barcodedummy.png
    

完成以上修改后,点击"Generate PDF"按钮即可正常生成包含图片的PDF文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:47:33