Flutter pdf file isnt saving and showing error - flutter

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.

Related

error in MemoryImage not defined in package pdf/widgets.dart

import 'dart:io';
import 'package:flutter/material.dart' as material ;
import 'package:flutter/services.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
class PdfParagraphApi {
static Future<void> generate(key) async {
final pdf = pw.Document();
final img = pw.MemoryImage(await rootBundle.load('assets/img.png')).buffer.asUint8List();
pdf.addPage(
pw.MultiPage(
build: (context) => <pw.Widget>[
pw.Image(img),
]),
);
}
}
i'm trying to create a pdf with an image inside it and i'm using the library pdf/widgets.dart to create the image as i found in flutters documentation but i'm facing a problem.
the error message is the following :
The function 'MemoryImage' isn't defined.
Try importing the library that defines 'MemoryImage', correcting the name to the name of an existing function, or defining a function named 'MemoryImage'.dartundefined_function
insert image into pdf not working
Replace pw.MemoryImage with material.MemoryImage, because MemoryImage comes from the painting library, which is included inside the material library.
Try to replace the below import:
import 'package:flutter/material.dart' as material ;
with this import 'package:flutter/material.dart';
Try this below way:
Imports you need
import 'package:flutter/material.dart';
import 'dart:math';
import 'dart:typed_data';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart ' as pw;
import 'dart:io';
import 'package:permission_handler/permission_handler.dart';
and in the top you need to define the image you want to print _imageFile = someImage:
Uint8List? _imageFile ;
Then this is the function to make an image to pdf and save it in the Downloads Folder
Future getPdf() async {
var random = Random();
var uniqueNum = random.nextInt(99999);
//get storage permission
Map<Permission, PermissionStatus> storagePermission = await [
Permission.storage,
].request();
pw.Document pdf = pw.Document();
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (context) {
return pw.Expanded(
child: pw.Image(pw.MemoryImage(_imageFile), fit: pw.BoxFit.contain),
);
},
),
);
String path = await ExternalPath.getExternalStoragePublicDirectory(
ExternalPath.DIRECTORY_DOWNLOADS);
String mainPath = "$path/Report$uniqueNum.pdf";
File pdfFile = File(mainPath);
pdfFile.writeAsBytesSync(await pdf.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();

How to convert PDF to image file by flutter

I am trying to print image to mobile Bluetooth thermal printer by ESC_POS_UTIL flutter Library, the Library support only image print or Text, so my plane is to render PDF and save to a PDF file by using pdf: ^3.3.0 Library which take job done perfectly, now there is only thing that how can i convert pdf to an image file and save to phone storage in order to print with ESC_POS_UTIL by FLUTTER
The code save pdf to file which is perfectly work
native_pdf_renderer is a flutter package that helps to render images from pdf files. Refer https://pub.dev/packages/native_pdf_renderer for more details.
Example code from package documentation:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:native_pdf_renderer/native_pdf_renderer.dart';
void main() async {
try {
final document = await PdfDocument.openAsset('assets/sample.pdf');
final page = await document.getPage(1);
final pageImage = await page.render(width: page.width, height: page.height);
await page.close();
runApp(MaterialApp(
home: Scaffold(
body: Center(
child: Image(
image: MemoryImage(pageImage.bytes),
),
),
),
color: Colors.white,
));
} on PlatformException catch (error) {
print(error);
}
}

PDF File generation with Flutter web

I'm in the process of Web'ifing a Flutter mobile application and attempting to get around the lack for support for Path Provider in Web.
I'm using the PDF (pdf: ^1.9.0) package to generate a PDF document and upload it to Google Drive and I'm trying to find out if I can generate and store the PDF In memory to make it web compatible.
Example current code using Path Provider.
createFile() async {
final downloads = await getApplicationSupportDirectory();
final file = File("${downloads.path}/$filename.pdf");
await file.writeAsBytes(pdf.save());
await GoogleDriveController.uploadFileToGoogleDrive(file.path);
}
Question: Is there a way to generate and store Fies in memory for web using Flutter web?
I managed to find a work around to generate the PDF and trigger a download via the browser instead and thought I should post incase anyone stumbles across this.
//Create PDF in Bytes
Uint8List pdfInBytes = pdf.save();
//Create blob and link from bytes
final blob = html.Blob([pdfInBytes], 'application/pdf');
final url = html.Url.createObjectUrlFromBlob(blob);
final anchor = html.document.createElement('a') as html.AnchorElement
..href = url
..style.display = 'none'
..download = 'pdf.pdf';
html.document.body.children.add(anchor);
//Trigger the download of this PDF in the browser.
RaisedButton(
child: Text('Press'),
onPressed: () {
anchor.click();
Navigator.pop(context);
},
)
My answer is a variant on Yonkee above specifically for flutter web. In this answer, I have added the imports required (dart:html and dart:typed_data) and added formatting of text as I needed that feature.
import 'package:flutter/material.dart';
import 'package:pdf/widgets.dart' as pw;
import 'dart:typed_data';
import 'dart:html' as html;
class PDFSave extends StatefulWidget {
#override
_PDFSaveState createState() => _PDFSaveState();
}
class _PDFSaveState extends State<PDFSave> {
final pdf = pw.Document();
var anchor;
savePDF() async {
Uint8List pdfInBytes = await pdf.save();
final blob = html.Blob([pdfInBytes], 'application/pdf');
final url = html.Url.createObjectUrlFromBlob(blob);
anchor = html.document.createElement('a') as html.AnchorElement
..href = url
..style.display = 'none'
..download = 'pdf.pdf';
html.document.body.children.add(anchor);
}
createPDF() async {
pdf.addPage(
pw.Page(
build: (pw.Context context) => pw.Column(
children: [
pw.Text('Hello World', style: pw.TextStyle(fontSize: 40)),
],
),
),
);
savePDF();
}
#override
void initState() {
super.initState();
createPDF();
}
#override
Widget build(BuildContext context) {
return Scaffold(backgroundColor: Colors.transparent,
appBar: AppBar(
title: Text('PDF Creator'),
),
body: Center(
child:RaisedButton(
child: Text('Press'),
onPressed: () {
anchor.click();
Navigator.pop(context);
},
)
));
}
}

How to get build and version number of Flutter app

I am currently developing an application which is currently in beta mode. Due to this, I would like to show them what version they are on. For example, "v1.0b10 - iOS". So far, I have got this code: Text("Build: V1.0b10 - " + (Platform.isIOS ? "iOS" : "Android")). How would I be able to get the build version and number within flutter?
You can use package_info_plus.
The versions are extracted from:
Android:
build.gradle, versionCode and versionName
iOS:
Info.plist, CFBundleVersion
Usage
Add the dependency
Add this to your package's pubspec.yaml file:
dependencies:
package_info_plus: ^1.0.6
Import the file into your dart file:
import 'package:package_info_plus/package_info_plus.dart';
if your method is marked as async:
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String appName = packageInfo.appName;
String packageName = packageInfo.packageName;
String version = packageInfo.version;
String buildNumber = packageInfo.buildNumber;
If you don't want to use await/async:
PackageInfo.fromPlatform().then((PackageInfo packageInfo) {
String appName = packageInfo.appName;
String packageName = packageInfo.packageName;
String version = packageInfo.version;
String buildNumber = packageInfo.buildNumber;
});
Note: This answer has been updated to reflect the fact that the package_info plugin is deprecated and redirects to package_info_plus.
Version name and build number
At development time, you can easily find the version name and build number of a Flutter or Dart project by inspecting pubspec.yaml. Here is an example:
version: 1.1.0+2
This is case the version name is 1.1.0 and the build number is 2.
However, if you want to get these values at runtime, you should use a plugin.
Add the dependency
In pubspec.yaml add the package_info_plus package.
dependencies:
package_info_plus: ^1.0.2
Update the version number to the current one.
Import the package
In the file that you need it, add the following import.
import 'package:package_info_plus/package_info_plus.dart';
Get the version name and code
In your code you can get the app version name and code like this:
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String version = packageInfo.version;
String code = packageInfo.buildNumber;
See also
How to set build and version number of Flutter app
How to get build and version number of Flutter Web app
install package_info_plus, then you can use it directly with future builder in your widget tree:
FutureBuilder<PackageInfo>(
future: PackageInfo.fromPlatform(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
return Align(
alignment: Alignment.bottomCenter,
child: Text(
'Version: ${snapshot.data!.version}',),
);
default:
return const SizedBox();
}
},
),
RE the multiple references to package_info, please note that this package has been deprecated and the recommended replacement is the Flutter Community Plus Plugins version, package_info_plus.
You can try new_version plugin. Using this plugin you can get installed App Version, Playstore App Version and app url which can redirect to playstore.
New Version Plugin
void versionCheck() async {
final NewVersion newVersion = NewVersion(context: context);
VersionStatus versionStatus = await newVersion.getVersionStatus();
if (versionStatus != null && versionStatus.canUpdate) {
await ConfirmDialog(
context: context,
title: 'Update Available',
body: Text('A new version, ${versionStatus.storeVersion}, is available.'),
acceptButton: 'Update Now',
cancelButton: 'Update Later'
).then((ConfirmAction res) async {
if (res == ConfirmAction.CONFIRM && await canLaunch(versionStatus.appStoreLink)) {
await launch(versionStatus.appStoreLink, forceWebView: false);
}
});
}
}
Custom Alert Dialog Box
enum ConfirmAction{ CONFIRM, CANCEL }
Future<ConfirmAction> ConfirmDialog({
BuildContext context,
String title,
Widget body,
String acceptButton,
String cancelButton
})
=> showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) => AlertDialog(
title: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 4,
children: <Widget>[
Text(title)
],
),
content: Wrap(
runSpacing: 10,
children: <Widget>[
body,
],
),
actions: <Widget>[
FlatButton(
padding: EdgeInsets.all(6),
child: Text(acceptButton ?? 'Confirm'),
onPressed: (){
Navigator.of(context, rootNavigator: true).pop(ConfirmAction.CONFIRM);
}
),
FlatButton(
padding: EdgeInsets.all(6),
child: Text(cancelButton ?? 'Cancel'),
onPressed: (){
Navigator.of(context, rootNavigator: true).pop(ConfirmAction.CANCEL);
}
),
],
)
);
For using it from command line or CLI, you need a pure Dart code.
I used the following script:
// ignore_for_file: avoid_print
import 'dart:io';
import 'package:path/path.dart';
import 'package:yaml/yaml.dart';
String pathToYaml = join(dirname(Platform.script.toFilePath()), '../pubspec.yaml');
Future<YamlMap> loadPubspec() async => loadYaml(await File(pathToYaml).readAsString());
void main() async {
var pubspec = await loadPubspec();
print(pubspec['version'].toString().split('+')[0]);
}
You can run it from the project root folder:
dart run scripts/get_version_name.dart
In Flutter mobile applications the version number is in pubspec.yaml file. like below:
version: 1.0.0+1
To get the version name and code, add the package_info dependency into pubspec.yaml file, like below:
dependencies:
package_info: ^0.4.0+16
And
import 'package:package_info/package_info.dart'; // import the package_info
Future<void> _initPackageInfo() async {
final _packageInfo = await PackageInfo.fromPlatform();
setState(() {
String AppName = _packageInfo.appName;
String PackageName = _packageInfo.packageName;
String AppVersion = _packageInfo.version;
String BuildNumber = _packageInfo.buildNumber;
String BuildSignature = _packageInfo.buildSignature;
});
}