貓哥說
保持熱情去改變!
今天這篇文章是讓你在客戶端完成 PDF 的創(chuàng)建,這樣能減輕服務(wù)器的壓力。
這是很有必要的,服務(wù)器的 CPU 資源很寶貴。
Flutter 插件 https://pub.dev/packages/pdf
- 功能有:
- 載入圖片
- 寫上文字
- 加密、簽名文件
- 也可以載入 pdf
老鐵記得 轉(zhuǎn)發(fā) ,貓哥會呈現(xiàn)更多 Flutter 好文~~~~
微信群 ducafecat
b 站 https://space.bilibili.com/404904528
原文
https://medium.com/flutterdevs/flutter-create-pdf-files-with-multiple-images-4458e813fe37
代碼
https://github.com/flutter-devs/flutter_pdf_create_view_demo
參考
- https://pub.dev/packages/pdf
- https://pub.dev/packages/path_provider/versions/2.0.1
- https://pub.dev/packages/syncfusion_flutter_pdfviewer/versions/19.1.64-beta
正文
[圖片上傳失敗...(image-104616-1623982135598)]
在 Flutter 不同的功能使您的應(yīng)用程序豐富的有用性,并給簡單的客戶端做東西內(nèi)的應(yīng)用程序和改善客戶端的經(jīng)驗,是一個專家合作是另外必不可少的開發(fā)人員。
有很多軟件包可以用來在應(yīng)用程序中打開 pdf,有些比較復(fù)雜,有些并不難執(zhí)行,在這里我將闡明可能最容易使用的方法。
在這個博客中,我們將探索 Flutter ー創(chuàng)建多張圖片的 PDF 文件。我們將實(shí)施一個演示程序,以顯示如何 Flutter 創(chuàng)建一個 pdf 文件與多個圖像使用的三個要素包在您的 Flutter 應(yīng)用程序。
狀態(tài)管理
簡介:
PDF 很可能是用于交換業(yè)務(wù)信息的最著名的文檔格式,因為內(nèi)容不能像不同配置那樣有效地更改。這樣可以保護(hù)我們的信息不受未經(jīng)批準(zhǔn)的更改的影響。一旦你知道了策略,這通常是一個簡單的互動,我會告訴你在你的任務(wù)中制作 pdf 文檔的最好方法。
對于這個演示,需要三個基本的軟件包。
- https://pub.dev/packages/pdf
- https://pub.dev/packages/path_provider/versions/2.0.1
- https://pub.dev/packages/syncfusion_flutter_pdfviewer/versions/19.1.64-beta
演示模塊:
[圖片上傳失敗...(image-fef52e-1623982135598)]
這個演示視頻顯示了如何在一個 Flutter 與多個圖像創(chuàng)建 pdf 文件。它顯示了 pdf 文件將如何使用這三個軟件包在您的 Flutter 應(yīng)用程序。它顯示當(dāng)用戶點(diǎn)擊一個創(chuàng)建按鈕,然后出現(xiàn) pdf,根據(jù)頁面有多個圖像。它會顯示在你的設(shè)備上。
實(shí)施方案:
- 第一步: 添加依賴項
將依賴項添加到 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/
- 第三步: 導(dǎo)入
import 'package:pdf/pdf.dart';
import 'package:path_provider/path_provider.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
- 第四步: 在應(yīng)用程序的根目錄中運(yùn)行 flutter 軟件包
如何實(shí)現(xiàn) dart 文件中的代碼:
你需要分別在你的代碼中實(shí)現(xiàn)它:
在 lib 文件夾中創(chuàng)建一個名為 pdf _ screen _ demo. dart 的新 dart 文件。
- 首先,讓我們創(chuàng)建一個基本的 PDF 文件:
在文件中創(chuàng)建一個 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 包有它自己的小部件庫存,為了調(diào)用這些庫存,我們需要導(dǎo)入 PDF 小部件作為一個變量名為 pw。
import 'package:pdf/widgets.dart' as pw;
為了構(gòu)造一個 PDF 格式,我們將通過調(diào)用 pw < widgetnme > 來調(diào)用小部件。
為了保存一個 pdf 文件,我們應(yīng)該做一個。文件()。這個不常見的小部件將保存已生成 PDF 的數(shù)據(jù),因此我們在 _ PdfScreenDemoState 中生成一個變量如何。
var pdf = pw.Document();
Lest’s create createPdfFile() method:
在這個模型中,我們的想法是制作一個多頁的帶有 a4 設(shè)計的 PDF。因為我們要添加的圖片的數(shù)量,頁面的數(shù)量可能是多個的,按照這些順序,現(xiàn)在制作一個多頁面小部件是個好兆頭。
在 MultiPage 小部件的構(gòu)建方法內(nèi)部,將有一個帶有 Header 的 Column 和 Divider,用于將實(shí)質(zhì)內(nèi)容與 Header 分離。在接下來的幾個階段中,我們將在本欄內(nèi)的分隔符下添加實(shí)質(zhì)內(nèi)容。
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(),
]),
];
}));
}
此后,我們應(yīng)該創(chuàng)建一個 savePdfFile ()方法。
它是一種異步方法,等待 IOS 或 Android 平臺的目錄。然后,該技術(shù)使用 ID 的名稱和目錄的 documentPath 創(chuàng)建一個記錄。你可以用任何你喜歡的方式來命名你的記錄,但是對于不同的 PDF 創(chuàng)建來說,更聰明的做法是為每個 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 ()轉(zhuǎn)換為 pdf 變量。如果不這樣做,該 pdf 將嘗試使另一個最近制作的 pdf 文件,這將導(dǎo)致一個有缺陷的 pdf 文件被制作。
如果您需要保存您的 PDF 文件的字節(jié),您可以利用下方的方法。
List<int> pdfBytes;
pdfBytes = await file.readAsBytes();
pdfFile base64Encode(pdfBytes);
除此之外,使用異步 onPressed 方法:
為了保存記錄,我們需要首先等待 createPdfFile ()策略。
onPressed: () async {
await createPdfFile();
savePdfFile();
},
好了,現(xiàn)在一切都安排好了。你可以點(diǎn)擊“創(chuàng)建一個 PDF 文件”按鈕來查看你的第一個基本 PDF 文檔。當(dāng)我們運(yùn)行應(yīng)用程序時,我們應(yīng)該得到屏幕的輸出,就像下面的屏幕截圖一樣。
- 讓我們用一個圖片創(chuàng)建一個 pdf 文件:
在 pdf 包中,你可以添加一個圖片。MemoryImage.因此,我們需要將圖片更改為內(nèi)存字節(jié)。
首先導(dǎo)入下面的軟件包。
import 'dart:typed_data';
import 'package:flutter/services.dart';
從那時起,將 createdffile 轉(zhuǎn)換為一個 async 方法,并添加這兩個變量。
final ByteData bytes = await rootBundle.load('assets/images/null_safety.png');
final Uint8List byteList = bytes.buffer.asUint8List();
第一個變量在資源圖片上更改為字節(jié),第二個變量在字節(jié)上更改為 Uint8List 字節(jié)列表。
然后,在這一點(diǎn)上添加一個 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 記錄中。現(xiàn)在重新啟動應(yīng)用程序,并嘗試制作另一個 PDF 文檔,以查看其中包含圖片的文件。當(dāng)我們運(yùn)行應(yīng)用程序時,我們應(yīng)該獲得屏幕輸出,就像下面的屏幕截圖一樣。
- 讓我們創(chuàng)建一個有多個圖片的 pdf 文件:
在演示的最后一步,我們將制作一個 pdf 構(gòu)建技術(shù),它可以用給定的各種圖像生成一條記錄。首先,我們需要制定一個策略,將圖片轉(zhuǎn)換為 Uint8List 設(shè)計。
在狀態(tài)小部件中,創(chuàng)建一個空白列表,用于將圖片放入 Uint8list。
List<Uint8List> imagesUint8list = [];
然后,我們應(yīng)該重構(gòu) createdffile 方法,并集中于另一種獲取圖片字節(jié)的技術(shù)。
getImageBytes(String assetImage) async {
final ByteData bytes = await rootBundle.load(assetImage);
final Uint8List byteList = bytes.buffer.asUint8List();
imagesUint8list.add(byteList);
}
現(xiàn)在我們將制作一個類型為 pw 的列表。createPdfFile ()技術(shù)中的小部件,它生成具有圖像標(biāo)題和圖像本身的 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();
注意: 這是緊急給一個特定的最大大小的圖片小部件,否則一個圖片可能會溢出頁面設(shè)計促使一個失敗的 pdf 創(chuàng)建。
Createdffile 最初會創(chuàng)建一個 for 循環(huán),將多個圖片更改為 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),
),
),
),
現(xiàn)在如何我們按下按鈕最后一次機(jī)會,使 PDF 文件與多個圖片。當(dāng)我們運(yùn)行應(yīng)用程序時,我們應(yīng)該得到屏幕的輸出,就像下面的屏幕截圖一樣。
代碼:
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
在這篇文章中,我解釋了創(chuàng)建 PDF 文件的基本結(jié)構(gòu)與多重圖像 Flutter; 您可以修改這個代碼根據(jù)您的選擇。這是一個小的介紹創(chuàng)建 PDF 文件與多圖像用戶交互從我這邊,它的工作使用 Flutter。
我希望這個博客將提供您在嘗試創(chuàng)建 PDF 文件與多個圖像在您的撲項目充分的信息。我們將向您展示介紹是什么?.制作一個演示程序為工作創(chuàng)建 PDF 文件與多個圖像和顯示當(dāng)用戶點(diǎn)擊一個創(chuàng)建按鈕,然后 PDF 發(fā)生,與多個圖像根據(jù)頁面使用所有三個軟件包在您的 Flutter 應(yīng)用程序。所以請嘗試一下。
? 貓哥
往期
開源
GetX Quick Start
https://github.com/ducafecat/getx_quick_start
新聞客戶端
https://github.com/ducafecat/flutter_learn_news
strapi 手冊譯文
微信討論群 ducafecat
系列集合
譯文
https://ducafecat.tech/categories/%E8%AF%91%E6%96%87/
開源項目
https://ducafecat.tech/categories/%E5%BC%80%E6%BA%90/
Dart 編程語言基礎(chǔ)
https://space.bilibili.com/404904528/channel/detail?cid=111585
Flutter 零基礎(chǔ)入門
https://space.bilibili.com/404904528/channel/detail?cid=123470
Flutter 實(shí)戰(zhàn)從零開始 新聞客戶端
https://space.bilibili.com/404904528/channel/detail?cid=106755
Flutter 組件開發(fā)
https://space.bilibili.com/404904528/channel/detail?cid=144262
Flutter Bloc
https://space.bilibili.com/404904528/channel/detail?cid=177519
Flutter Getx4
https://space.bilibili.com/404904528/channel/detail?cid=177514
Docker Yapi
https://space.bilibili.com/404904528/channel/detail?cid=130578