猫哥说

放弃激情去扭转!

明天这篇文章是让你在客户端实现 PDF 的创立,这样能加重服务器的压力。

这是很有必要的,服务器的 CPU 资源很贵重。

Flutter 插件 https://pub.dev/packages/pdf

  • 性能有:

    • 载入图片
    • 写上文字
    • 加密、签名文件
    • 也能够载入 pdf

老铁记得 转发 ,猫哥会出现更多 Flutter 好文~~~~

微信群 ducafecat

b 站 https://space.bilibili.com/40...

原文

https://medium.com/flutterdev...

代码

https://github.com/flutter-de...

参考

  • https://pub.dev/packages/pdf
  • https://pub.dev/packages/path...
  • https://pub.dev/packages/sync...

注释

在 Flutter 不同的性能使您的应用程序丰盛的有用性,并给简略的客户端做货色内的应用程序和改善客户端的教训,是一个专家单干是另外必不可少的开发人员。

有很多软件包能够用来在应用程序中关上 pdf,有些比较复杂,有些并不难执行,在这里我将说明可能最容易应用的办法。

在这个博客中,咱们将摸索 Flutter ー创立多张图片的 PDF 文件。咱们将施行一个演示程序,以显示如何 Flutter 创立一个 pdf 文件与多个图像应用的三个因素包在您的 Flutter 应用程序。

状态治理

简介:

PDF 很可能是用于替换业务信息的最驰名的文档格局,因为内容不能像不同配置那样无效地更改。这样能够爱护咱们的信息不受未经批准的更改的影响。一旦你晓得了策略,这通常是一个简略的互动,我会通知你在你的工作中制作 pdf 文档的最好办法。

对于这个演示,须要三个根本的软件包。
  • https://pub.dev/packages/pdf
  • https://pub.dev/packages/path...
  • https://pub.dev/packages/sync...

演示模块:

这个演示视频显示了如何在一个 Flutter 与多个图像创立 pdf 文件。它显示了 pdf 文件将如何应用这三个软件包在您的 Flutter 应用程序。它显示当用户点击一个创立按钮,而后呈现 pdf,依据页面有多个图像。它会显示在你的设施上。

实施方案:

  • 第一步: 增加依赖项

将依赖项增加到 pubspec ー yaml 文件。

dependencies:  flutter:    sdk: flutter  cupertino_icons: ^1.0.2  path_provider: ^2.0.1  pdf: ^3.3.0  syncfusion_flutter_pdfviewer: ^19.1.64-beta
  • 第二步: 增加 assets

将 assets 增加到 pubspec ー yaml 文件。

assets:  - assets/images/
  • 第三步: 导入
import 'package:pdf/pdf.dart';import 'package:path_provider/path_provider.dart';import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
  • 第四步: 在应用程序的根目录中运行 flutter 软件包

如何实现 dart 文件中的代码:

你须要别离在你的代码中实现它:

在 lib 文件夹中创立一个名为 pdf screen demo. dart 的新 dart 文件。
  • 首先,让咱们创立一个根本的 PDF 文件:

在文件中创立一个 StatefulWidget,名为 PdfScreenDemo。

String pdfFile = '';

一个根本的用户界面,咱们有一个凸起的按钮,使咱们的 PDF 文件和一个可见性小部件揭示 PDF 浏览器一旦 PDF 记录。要查看 PDF 记录,咱们将应用 syncfusion/flutter/pdfviewer 包的 SfPdfViewer.file 小部件,在这个小部件中,咱们将制作一个文档,其形式与咱们制作的 PDF 相似。

Column(  mainAxisAlignment: MainAxisAlignment.center,  children: [      Visibility(          visible: pdfFile.isNotEmpty,          child: SfPdfViewer.file(File(pdfFile),              canShowScrollHead: false, canShowScrollStatus:           false),        ),    RaisedButton(        color: Colors.tealAccent,        onPressed: () {        },        child: Text('Create a Pdf File')),  ],),

PDF 包有它本人的小部件库存,为了调用这些库存,咱们须要导入 PDF 小部件作为一个变量名为 pw。

import 'package:pdf/widgets.dart' as pw;
为了结构一个 PDF 格局,咱们将通过调用 pw < widgetnme > 来调用小部件。

为了保留一个 pdf 文件,咱们应该做一个。文件()。这个不常见的小部件将保留已生成 PDF 的数据,因而咱们在 \_ PdfScreenDemoState 中生成一个变量如何。

var pdf = pw.Document();
Lest’s create createPdfFile() method:

在这个模型中,咱们的想法是制作一个多页的带有 a4 设计的 PDF。因为咱们要增加的图片的数量,页面的数量可能是多个的,依照这些程序,当初制作一个多页面小部件是个好兆头。

在 MultiPage 小部件的构建办法外部,将有一个带有 Header 的 Column 和 Divider,用于将本质内容与 Header 拆散。在接下来的几个阶段中,咱们将在本栏内的分隔符下增加本质内容。

createPdfFile() {  pdf.addPage(pw.MultiPage(      margin: pw.EdgeInsets.all(10),      pageFormat: PdfPageFormat.a4,      build: (pw.Context context) {        return <pw.Widget>[          pw.Column(              crossAxisAlignment: pw.CrossAxisAlignment.center,              mainAxisSize: pw.MainAxisSize.min,              children: [                pw.Text('Create a basic PDF',                    textAlign: pw.TextAlign.center,                    style: pw.TextStyle(fontSize: 26)),                pw.Divider(),              ]),        ];      }));}
尔后,咱们应该创立一个 savePdfFile ()办法。

它是一种异步办法,期待 IOS 或 Android 平台的目录。而后,该技术应用 ID 的名称和目录的 documentPath 创立一个记录。你能够用任何你喜爱的形式来命名你的记录,然而对于不同的 PDF 创立来说,更聪慧的做法是为每个 PDF 文档都起一个非凡的名字。

最初,该办法将 PDF 保留为文件。Path 和 value 被赋给 setState 策略中的 pdfFile 变量,以便稍后刷新 UI。

savePdfFile() async {Directory documentDirectory = await getApplicationDocumentsDirectory();String documentPath = documentDirectory.path;String id = DateTime.now().toString();File file = File("$documentPath/$id.pdf");file.writeAsBytesSync(await pdf.save());setState(() {pdfFile = file.path;pdf = pw.Document();});}
重要提醒: 任命民主党人是基本。在保留 pdf 文件之后,将 Document ()转换为 pdf 变量。如果不这样做,该 pdf 将尝试使另一个最近制作的 pdf 文件,这将导致一个有缺点的 pdf 文件被制作。

如果您须要保留您的 PDF 文件的字节,您能够利用下方的办法。

List<int> pdfBytes;pdfBytes = await file.readAsBytes();pdfFile base64Encode(pdfBytes);
除此之外,应用异步 onPressed 办法:

为了保留记录,咱们须要首先期待 createPdfFile ()策略。

onPressed: () async {  await createPdfFile();  savePdfFile();},

好了,当初所有都安顿好了。你能够点击“创立一个 PDF 文件”按钮来查看你的第一个根本 PDF 文档。当咱们运行应用程序时,咱们应该失去屏幕的输入,就像上面的屏幕截图一样。

  • 让咱们用一个图片创立一个 pdf 文件:

在 pdf 包中,你能够增加一个图片。MemoryImage.因而,咱们须要将图片更改为内存字节。

首先导入上面的软件包。
import 'dart:typed_data';import 'package:flutter/services.dart';

从那时起,将 createdffile 转换为一个 async 办法,并增加这两个变量。

final ByteData bytes = await rootBundle.load('assets/images/null_safety.png');final Uint8List byteList = bytes.buffer.asUint8List();

第一个变量在资源图片上更改为字节,第二个变量在字节上更改为 Uint8List 字节列表。

而后,在这一点上增加一个 pw 图像小部件在分隔符上面。

createPdfFile() async {  final ByteData bytes =      await rootBundle.load('assets/images/null_safety.png');  final Uint8List byteList = bytes.buffer.asUint8List();  pdf.addPage(pw.MultiPage(      margin: pw.EdgeInsets.all(10),      pageFormat: PdfPageFormat.a4,      build: (pw.Context context) {        return <pw.Widget>[          pw.Column(              crossAxisAlignment: pw.CrossAxisAlignment.center,              mainAxisSize: pw.MainAxisSize.min,              children: [                pw.Text('Flutter Pdf File with Image',                    textAlign: pw.TextAlign.center,                    style: pw.TextStyle(fontSize: 26)),                pw.Divider(),              ]),          pw.SizedBox(height: 70),          pw.Image(              pw.MemoryImage(                byteList,              ),              height: 300,              fit: pw.BoxFit.fitHeight),        ];      }));}

MemoryImage 承受 byteList 作为地位竞争,将图片传送到 pdf 记录中。当初重新启动应用程序,并尝试制作另一个 PDF 文档,以查看其中蕴含图片的文件。当咱们运行应用程序时,咱们应该取得屏幕输入,就像上面的屏幕截图一样。

  • 让咱们创立一个有多个图片的 pdf 文件:

在演示的最初一步,咱们将制作一个 pdf 构建技术,它能够用给定的各种图像生成一条记录。首先,咱们须要制订一个策略,将图片转换为 Uint8List 设计。

在状态小部件中,创立一个空白列表,用于将图片放入 Uint8list。
List<Uint8List> imagesUint8list = [];
而后,咱们应该重构 createdffile 办法,并集中于另一种获取图片字节的技术。
getImageBytes(String assetImage) async {    final ByteData bytes = await rootBundle.load(assetImage);    final Uint8List byteList = bytes.buffer.asUint8List();    imagesUint8list.add(byteList);  }

当初咱们将制作一个类型为 pw 的列表。createPdfFile ()技术中的小部件,它生成具备图像题目和图像自身的 Column。

final List<pw.Widget> pdfImages = imagesUint8list.map((image) {      return pw.Padding(          padding: pw.EdgeInsets.symmetric(vertical: 20, horizontal:    10),          child: pw.Column(              crossAxisAlignment: pw.CrossAxisAlignment.center,              mainAxisSize: pw.MainAxisSize.max,              children: [                pw.Text(                    'Image'                            ' ' +                        (imagesUint8list                                    .indexWhere((element) => element                                   == image) +                                1)                            .toString(),                    style: pw.TextStyle(fontSize: 22)),                pw.SizedBox(height: 10),                pw.Image(                    pw.MemoryImage(                      image,                    ),                    height: 400,                    fit: pw.BoxFit.fitHeight)              ]));    }).toList();
留神: 这是紧急给一个特定的最大大小的图片小部件,否则一个图片可能会溢出页面设计促使一个失败的 pdf 创立。

Createdffile 最后会创立一个 for 循环,将多个图片更改为 Uint8List。稍后,它将制作一个带有头部的图片列表。最初,pdfImages 将作为子文件显示在 pdf 的根本列中。

createPdfFile() async {    for (String image in assetImages) await getImageBytes(image);    final List<pw.Widget> images = imagesUint8list.map((image) {      return pw.Padding(          padding: pw.EdgeInsets.symmetric(vertical: 20, horizontal:  10),          child: pw.Column(              crossAxisAlignment: pw.CrossAxisAlignment.center,              mainAxisSize: pw.MainAxisSize.max,              children: [                pw.Text(                    'Image'                            ' ' +                        (imagesUint8list                                   .indexWhere((element) => element                             == image) +                                1)                            .toString(),                    style: pw.TextStyle(fontSize: 22)),                pw.SizedBox(height: 10),                pw.Image(                    pw.MemoryImage(                      image,                    ),                    height: 400,                    fit: pw.BoxFit.fitHeight)              ]));    }).toList();    pdf.addPage(pw.MultiPage(        margin: pw.EdgeInsets.all(10),        pageFormat: PdfPageFormat.a4,        build: (pw.Context context) {          return <pw.Widget>[            pw.Column(                crossAxisAlignment: pw.CrossAxisAlignment.center,                mainAxisSize: pw.MainAxisSize.min,                children: [                  pw.Text('Create a Simple PDF',                      textAlign: pw.TextAlign.center,                      style: pw.TextStyle(fontSize: 26)),                  pw.Divider(),                ]),            pw.Column(                crossAxisAlignment: pw.CrossAxisAlignment.center,                mainAxisSize: pw.MainAxisSize.max,                children: pdfImages),          ];        }));  }
另一个步骤是用 SingleChildScrollView 和 Expanded 小部件包装可见性小部件。
Expanded(              child: SingleChildScrollView(                child: Visibility(                  visible: pdfFile.isNotEmpty,                  child: SfPdfViewer.file(File(pdfFile),                      canShowScrollHead: false, canShowScrollStatus: false),                ),              ),            ),

当初如何咱们按下按钮最初一次机会,使 PDF 文件与多个图片。当咱们运行应用程序时,咱们应该失去屏幕的输入,就像上面的屏幕截图一样。

代码:

import 'dart:io';import 'dart:typed_data';import 'package:flutter/services.dart';import 'package:path_provider/path_provider.dart';import 'package:pdf/pdf.dart';import 'package:pdf/widgets.dart' as pw;import 'package:flutter/material.dart';import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';class PdfScreenDemo extends StatefulWidget {  @override  _PdfScreenDemoState createState() => _PdfScreenDemoState();}class _PdfScreenDemoState extends State<PdfScreenDemo> {  String pdfFile = '';  var pdf = pw.Document();  static const List<String> assetImages = [    'assets/images/null_safety.png',    'assets/images/stream.png',    'assets/images/error_handling.jpg'  ];  List<Uint8List> imagesUint8list = [];  @override  @override  Widget build(BuildContext context) {    return SafeArea(      child: Scaffold(        body: Center(          child: Column(            mainAxisAlignment: MainAxisAlignment.center,            children: [              Expanded(                child: SingleChildScrollView(                  child: Visibility(                    visible: pdfFile.isNotEmpty,                    child: SfPdfViewer.file(File(pdfFile),                        canShowScrollHead: false, canShowScrollStatus: false),                  ),                ),              ),              RaisedButton(                  color: Colors.tealAccent,                  onPressed: () async {                    await createPdfFile();                    savePdfFile();                  },                  child: Text('Create a Pdf File')),            ],          ),        ),      ),    );  }  getImageBytes(String assetImage) async {    final ByteData bytes = await rootBundle.load(assetImage);    final Uint8List byteList = bytes.buffer.asUint8List();    imagesUint8list.add(byteList);    print(imagesUint8list.length);  }  createPdfFile() async {    for (String image in assetImages) await getImageBytes(image);    final List<pw.Widget> pdfImages = imagesUint8list.map((image) {      return pw.Padding(          padding: pw.EdgeInsets.symmetric(vertical: 50, horizontal: 10),          child: pw.Column(              crossAxisAlignment: pw.CrossAxisAlignment.center,              mainAxisSize: pw.MainAxisSize.max,              children: [                pw.Text(                    'Image'                            ' ' +                        (imagesUint8list                                    .indexWhere((element) => element == image) +                                1)                            .toString(),                    style: pw.TextStyle(fontSize: 22)),                pw.SizedBox(height: 30),                pw.Image(                    pw.MemoryImage(                      image,                    ),                    height: 300,                    fit: pw.BoxFit.fitHeight)              ]));    }).toList();    pdf.addPage(pw.MultiPage(        margin: pw.EdgeInsets.all(10),        pageFormat: PdfPageFormat.a4,        build: (pw.Context context) {          return <pw.Widget>[            pw.Column(                crossAxisAlignment: pw.CrossAxisAlignment.center,                mainAxisSize: pw.MainAxisSize.min,                children: [                  pw.Text('Flutter Pdf File with Multiple Image',                      textAlign: pw.TextAlign.center,                      style: pw.TextStyle(fontSize: 26)),                  pw.Divider(),                ]),            pw.Column(                crossAxisAlignment: pw.CrossAxisAlignment.center,                mainAxisSize: pw.MainAxisSize.max,                children: pdfImages),          ];        }));  }  savePdfFile() async {    Directory documentDirectory = await getApplicationDocumentsDirectory();    String documentPath = documentDirectory.path;    String id = DateTime.now().toString();    File file = File("$documentPath/$id.pdf");    file.writeAsBytesSync(await pdf.save());    setState(() {      pdfFile = file.path;      pdf = pw.Document();    });  }}

Conclusion

在这篇文章中,我解释了创立 PDF 文件的根本构造与多重图像 Flutter; 您能够批改这个代码依据您的抉择。这是一个小的介绍创立 PDF 文件与多图像用户交互从我这边,它的工作应用 Flutter。

我心愿这个博客将提供您在尝试创立 PDF 文件与多个图像在您的扑我的项目充沛的信息。咱们将向您展现介绍是什么?.制作一个演示程序为工作创立 PDF 文件与多个图像和显示当用户点击一个创立按钮,而后 PDF 产生,与多个图像依据页面应用所有三个软件包在您的 Flutter 应用程序。所以请尝试一下。


© 猫哥

https://ducafecat.tech/

https://github.com/ducafecat

往期

开源

GetX Quick Start

https://github.com/ducafecat/...

新闻客户端

https://github.com/ducafecat/...

strapi 手册译文

https://getstrapi.cn

微信探讨群 ducafecat

系列汇合

译文

https://ducafecat.tech/catego...

开源我的项目

https://ducafecat.tech/catego...

Dart 编程语言根底

https://space.bilibili.com/40...

Flutter 零根底入门

https://space.bilibili.com/40...

Flutter 实战从零开始 新闻客户端

https://space.bilibili.com/40...

Flutter 组件开发

https://space.bilibili.com/40...

Flutter Bloc

https://space.bilibili.com/40...

Flutter Getx4

https://space.bilibili.com/40...

Docker Yapi

https://space.bilibili.com/40...