貓哥說
保持熱情去改變!
今天這篇文章是讓你在客戶端完成 PDF 的創(chuàng)建址否,這樣能減輕服務器的壓力。
這是很有必要的搜囱,服務器的 CPU 資源很寶貴霎肯。
Flutter 插件 https://pub.dev/packages/pdf
- 功能有:
- 載入圖片
- 寫上文字
- 加密、簽名文件
- 也可以載入 pdf
老鐵記得 轉發(fā) 慢哈,貓哥會呈現更多 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 不同的功能使您的應用程序豐富的有用性蔓钟,并給簡單的客戶端做東西內的應用程序和改善客戶端的經驗,是一個專家合作是另外必不可少的開發(fā)人員卵贱。
有很多軟件包可以用來在應用程序中打開 pdf滥沫,有些比較復雜,有些并不難執(zhí)行键俱,在這里我將闡明可能最容易使用的方法兰绣。
在這個博客中,我們將探索 Flutter ー創(chuàng)建多張圖片的 PDF 文件编振。我們將實施一個演示程序缀辩,以顯示如何 Flutter 創(chuàng)建一個 pdf 文件與多個圖像使用的三個要素包在您的 Flutter 應用程序。
狀態(tài)管理
簡介:
PDF 很可能是用于交換業(yè)務信息的最著名的文檔格式,因為內容不能像不同配置那樣有效地更改雌澄。這樣可以保護我們的信息不受未經批準的更改的影響。一旦你知道了策略杯瞻,這通常是一個簡單的互動镐牺,我會告訴你在你的任務中制作 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 應用程序旗唁。它顯示當用戶點擊一個創(chuàng)建按鈕畦浓,然后出現 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 文件夾中創(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 包有它自己的小部件庫存朵诫,為了調用這些庫存,我們需要導入 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(),
]),
];
}));
}
此后怎爵,我們應該創(chuàng)建一個 savePdfFile ()方法特石。
它是一種異步方法,等待 IOS 或 Android 平臺的目錄鳖链。然后姆蘸,該技術使用 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 ()轉換為 pdf 變量慨菱。如果不這樣做焰络,該 pdf 將嘗試使另一個最近制作的 pdf 文件,這將導致一個有缺陷的 pdf 文件被制作符喝。
如果您需要保存您的 PDF 文件的字節(jié)闪彼,您可以利用下方的方法。
List<int> pdfBytes;
pdfBytes = await file.readAsBytes();
pdfFile base64Encode(pdfBytes);
除此之外协饲,使用異步 onPressed 方法:
為了保存記錄畏腕,我們需要首先等待 createPdfFile ()策略。
onPressed: () async {
await createPdfFile();
savePdfFile();
},
好了茉稠,現在一切都安排好了描馅。你可以點擊“創(chuàng)建一個 PDF 文件”按鈕來查看你的第一個基本 PDF 文檔。當我們運行應用程序時而线,我們應該得到屏幕的輸出铭污,就像下面的屏幕截圖一樣恋日。
- 讓我們用一個圖片創(chuàng)建一個 pdf 文件:
在 pdf 包中,你可以添加一個圖片嘹狞。MemoryImage.因此岂膳,我們需要將圖片更改為內存字節(jié)。
首先導入下面的軟件包磅网。
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();
第一個變量在資源圖片上更改為字節(jié),第二個變量在字節(jié)上更改為 Uint8List 字節(jié)列表速蕊。
然后嫂丙,在這一點上添加一個 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 文檔唉锌,以查看其中包含圖片的文件隅肥。當我們運行應用程序時,我們應該獲得屏幕輸出袄简,就像下面的屏幕截圖一樣腥放。
- 讓我們創(chuàng)建一個有多個圖片的 pdf 文件:
在演示的最后一步,我們將制作一個 pdf 構建技術绿语,它可以用給定的各種圖像生成一條記錄秃症。首先,我們需要制定一個策略吕粹,將圖片轉換為 Uint8List 設計种柑。
在狀態(tài)小部件中,創(chuàng)建一個空白列表匹耕,用于將圖片放入 Uint8list聚请。
List<Uint8List> imagesUint8list = [];
然后,我們應該重構 createdffile 方法稳其,并集中于另一種獲取圖片字節(jié)的技術驶赏。
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 創(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),
),
),
),
現在如何我們按下按鈕最后一次機會荆萤,使 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
在這篇文章中煮落,我解釋了創(chuàng)建 PDF 文件的基本結構與多重圖像 Flutter; 您可以修改這個代碼根據您的選擇敞峭。這是一個小的介紹創(chuàng)建 PDF 文件與多圖像用戶交互從我這邊,它的工作使用 Flutter蝉仇。
我希望這個博客將提供您在嘗試創(chuàng)建 PDF 文件與多個圖像在您的撲項目充分的信息旋讹。我們將向您展示介紹是什么?.制作一個演示程序為工作創(chuàng)建 PDF 文件與多個圖像和顯示當用戶點擊一個創(chuàng)建按鈕轿衔,然后 PDF 發(fā)生沉迹,與多個圖像根據頁面使用所有三個軟件包在您的 Flutter 應用程序。所以請嘗試一下害驹。
? 貓哥
往期
開源
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 編程語言基礎
https://space.bilibili.com/404904528/channel/detail?cid=111585
Flutter 零基礎入門
https://space.bilibili.com/404904528/channel/detail?cid=123470
Flutter 實戰(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