How to create multi pages pdf in flutter with images? - flutter

I have a list of file image paths. I need to create pdf from these images. How can I do it? I already know how to create pdf from a single image using pdf package.

Replace Page widget with MultiPage widget, default max pages is 20.
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
final pdf = Document();
pdf.addPage(
MultiPage(
pageFormat: PdfPageFormat.a4,
build: (Context context) => <Widget>[*/your widgets here*/],
)
)

Check out pdf library. The documentation contains example codes which will let you create a pdf file with multiple pages with images inside.
final image = PdfImage.file(
pdf.document,
bytes: File('test.webp').readAsBytesSync(),
);
final pdf = pw.Document();
final image = PdfImage.file(
pdf.document,
bytes: File('test.webp').readAsBytesSync(),
);
pdf.addPage(pw.Page(
build: (pw.Context context) {
return pw.Center(
child: pw.Image(image),
); // Center
})); // Page
final file = File("example.pdf");
await file.writeAsBytes(pdf.save());

Related

How to preview pdf in Scaffold - Flutter

I'm using the flutter pdf producer package and I'm trying to preview or display it in the scaffold but so far unable to do it
package link : https://pub.dev/packages/pdf
here is my code
class _PreviewInvoiceState extends State<PreviewInvoice> {
// pdf producer
void makePdf(){
final document = pw.Document();
document.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (pw.Context context) {
return pw.Center(child: pw.Text('hello world'));
}
)
);
}
#override
Widget build(BuildContext context) {
return Scaffold(); // trying to display it in the scaffold body property
}
}
The pdf package is for creating pdf. To view it you have to save it to storage with
// On Flutter, use the [path_provider](https://pub.dev/packages/path_provider) library:
// final output = await getTemporaryDirectory();
// final file = File("${output.path}/example.pdf");
final file = File("example.pdf");
await file.writeAsBytes(await pdf.save());
And to view you have to use package like pdf_viewer_flutter.

Add New Page in MultiPage Pdf Flutter

I use the pdf library and MultiPage, and I want to repeat the specific widget so that each widget is on a separate page. How do I do that?
I don't want to use addPage because I have a header, footer and some formats don't want to repeat it in every add page.
How can I add a new page to a MultiPage that already has the same formats?
// Create a PDF document.
final doc = pw.Document();
_logo = await rootBundle.loadString('assets/logo.svg');
_bgShape = await rootBundle.loadString('assets/invoice.svg');
=====> first_ Add page to the PDF <=======
doc.addPage(
pw.MultiPage(
pageTheme: _buildTheme(
pageFormat,
await PdfGoogleFonts.robotoRegular(),
await PdfGoogleFonts.robotoBold(),
await PdfGoogleFonts.robotoItalic(),
),
header: _buildHeader,
footer: _buildFooter,
build: (context) => [
//Insert to widget
],
),
);
======> second_ Add page to the PDF <========
doc.addPage(
pw.MultiPage(
pageTheme: _buildTheme(
pageFormat,
await PdfGoogleFonts.robotoRegular(),
await PdfGoogleFonts.robotoBold(),
await PdfGoogleFonts.robotoItalic(),
),
header: _buildHeader,
footer: _buildFooter,
build: (context) => [
//Insert to widget
],
),
);
// Return the PDF file content
return doc.save();

How to load image from assets folder inside a pdf in Flutter web?

We want to show image on a pdf from assets folder in Flutter web application:
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:flutter/material.dart';
.............
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Container(
height: 400,
width: 900,
child: PdfPreview(
build: (format) => _generatePdf(format, "SOME TITLE"),
)),
),
]));
}
Future<Uint8List> _generatePdf(PdfPageFormat format) async {
final pdf = pw.Document();
pdf.addPage(
pw.Page(
pageFormat: format,
build: (context) {
return pw.Image(AssetImage('assets/imglogo.png')); //This line gives the error
}));
return pdf.save();
}
This code gives error:
The argument type 'AssetImage' can't be assigned to the parameter type 'ImageProvider'
The documentation addresses only two cases To load an image from a file:(dart.io is not supported on the web), and To load an image from the network using the printing package:, which is not the case, so we tried the solutions provided here: 1,2, but each one gives a different exception.
Is there another approach to achieve this?
You can convert your ByteData directly to Uint8List as shown in the example code below. This can then be passed to the MemoryImage constructor:
Future<void> addPage(pw.Document pdf, String filename) async {
final imageByteData = await rootBundle.load('assets/$filename');
// Convert ByteData to Uint8List
final imageUint8List = imageByteData.buffer
.asUint8List(imageByteData.offsetInBytes, imageByteData.lengthInBytes);
final image = pw.MemoryImage(imageUint8List);
pdf.addPage(
pw.Page(
build: (pw.Context context) {
return pw.Center(
child: pw.Image(image),
); // Center
},
),
);
}
To achieve this you can get the asset image as a file, and then use this file in the PDF. If I take your code, we can add a function to get a File representation of your asset image :
Future<File> getImageFileFromAssets(String path) async {
final byteData = await rootBundle.load('assets/$path');
final file = File('${(await getTemporaryDirectory()).path}/$path');
await file.writeAsBytes(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
To make it works, you need to add path_provider to your dependencies.
Then you can use this function in your pdf generation function :
final pdf = pw.Document();
final file = await getImageFileFromAssets(yourpath);
final image = pw.MemoryImage(
file.readAsBytesSync(),
);
pdf.addPage(pw.Page(
pageFormat: format,
build: (context) {
return pw.Image(image);
}));
return pdf.save();

Flutter pdf file isnt saving and showing error

I am trying to simple generate and save pdf issue is its showing error in my code
I am doing like this
import 'package:path_provider/path_provider.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
onTap: () async{
final pdf = pw.Document();
pdf.addPage(
pw.Page(
build: (pw.Context context) => pw.Center(
child: pw.Text('Hello World!'),
),
),
);
// Share.shareFiles([pdf], text: 'Reports');
final output = await getTemporaryDirectory();
final path = "${output.path}/temp.pdf";
final file = File(path); // here its showing error 2 positional
await file.writeAsBytes(pdf.save()); // here its showing The method 'writeAsBytes' isn't defined for the type 'File'.
},
Plugin versions
pdf: 2.1.0 & path_provider: ^2.0.2
I search every where but I didnt find any solution cant find it so why I am getting this error -_-
Use io library to write the file:
import 'dart:io' as io;
onTap: () async{
final pdf = pw.Document();
pdf.addPage(
pw.Page(
build: (pw.Context context) => pw.Center(
child: pw.Text('Hello World!'),
),
),
);
// Share.shareFiles([pdf], text: 'Reports');
//replace your code to save file from bellow
final output = await getTemporaryDirectory();
final path = "${output.path}/temp.pdf";
final file = await io.File(path).writeAsBytes(pdf.save());
},
The error would be due to methods defined in the pdf library. You can use default io library to solve that.

Flutter: Print image with right orientation and size A4

I want to print an image in flutter. I use the package "printing 3.5.0". My problem is now I want use the hole space of the page. But when I put the orientation or size, both parameters are ignored.
_printImage(GlobalKey globalKey) async {
final pdf = new PdfDocument();
final page = new PdfPage(pdf, pageFormat: PdfPageFormat.a4);
final doc = pw.Document();
final g = page.getGraphics();
RenderRepaintBoundary boundary =
globalKey.currentContext.findRenderObject();
ui.Image _image = await boundary.toImage();
var bytes = await _image.toByteData(format: ui.ImageByteFormat.rawRgba);
PdfImage image = new PdfImage(pdf,
image: bytes.buffer.asUint8List(),
width: _image.width,
height: _image.height);
doc.addPage(pw.Page(build: (pw.Context context) {
return pw.Center(
child: pw.Image(image),
); // Center
}));
g.drawImage(image, 20.0, 0.0);
Printing.layoutPdf(onLayout: (pageFormat) {
return pdf.save();
});
}
Even if I adjust the width and height of the image, the whole page is not used.
Does not exist a parameter that automatically scales the image on the whole page and observes the orientation?
I'm grateful for any help.