I'm making a travel app about Crete where people can look up the most important things to see. They can also add documents to their own trips, which is a collection on firestore "Selected".
I want people to be able to generate a pdf from their selected items, to save on their Android/Iphone.
I have a seperate class for generating the pdf..
But how do I pass snapshot.data() to the other class?
onTap: () async {
getSelectedItems();
final pdfFile = await PdfApi.generateCenteredText(data);
PdfApi.openFile(pdfFile);
},
getSelectedItems(){
mySelectedTrips.get().then((querySnapshot) {
querySnapshot.docs.forEach((snapshot) {
setState(() {
data = snapshot.data();
uid = snapshot['uid'];
description = snapshot['description'];
image = snapshot['image'];
});
});
});
}
Hi here is a short example how to create a pdf with one page.
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
class PdfCreator {
void createPdf(Snapshot snapshot) async {
final Document pdf = Document();
final page = Page(
pageFormat: PdfPageFormat.a4,
build: (Context context) {
return Column(
children: [
Text(snapshot.snapshot['description']),
Text(snapshot.snapshot['uid'].toString()),
Image(MemoryImage(snapshot['image'])),
],
);
},
);
pdf.addPage(page);
// Save file
final output = await getTemporaryDirectory();
var path = "${output.path}/test.pdf";
final file = File(path);
await file.writeAsBytes(await pdf.save());
}
}
You can enhance it and create one page per element in your foreach loop and and it to the pdf and so on.
Hint: if you want to use flutter widgets and pdf widgets in one file you can import pdf as p for example:
import 'package:pdf/widgets.dart' as p;
...
final flutterWidget = Text('abc');
final pdfWidget = p.Text('def');
Related
So I have this code that picks the image
Container(
child: ElevatedButton(
onPressed: () async {
result = await FilePicker.platform
.pickFiles(allowMultiple: true);
if (result == null) {
print("No file selected");
} else {
setState(() {
result?.files.forEach((element) {
attachmentController.text =
element.name;
statusController.text = "pending";
});
});
result?.files.forEach((element) {
print(element.name);
});
}
},
and I wanted to send this image to the backend of laravel but first, I have an attachment controller that saves the element.name but turns out it's just a name. May I please know how to save the image in the controller and if any links to show how to save that in the laravel backend please?
Thank you
If you are only picking images i will suggest you to use the image_picker package.
In your widget file :
File? image;
...
image= await ImagePicker.pickImage(source: ImageSource.gallery);
setState({});
You can use Image.file, widget factory method to show the image.
In your Api file :
import 'package:http/http.dart' as http;
import 'dart:convert';
...
var response = await http.post('example.com/api',
body: {
'image': base64Encode(await imageFile.readAsBytes()),
},
);
Depending on your Laravel you handle the request, decode it from base64 and save it to a folder.
Below is a snippet of code from a function that uploads a generated QR code (using the qr_flutter package) to firebase storage; then gets the firebase storage url to save in a custom model that is uploaded to firebase firestore (not shown).
This works fine, however I want to upload a file that consists of the QR code bounded by title text above and address text below. (Essentially a Column with children [title, qrFile, address]).
My question is: How do I combine Text and my qrFile into a single image file that I can upload to firebase storage?
String qrString = 'qr_data_here';
final qrValidationResult = QrValidator.validate(
data: qrString,
version: QrVersions.auto,
errorCorrectionLevel: QrErrorCorrectLevel.L,
);
if (qrValidationResult.status == QrValidationStatus.valid) {
final qrCode = qrValidationResult.qrCode;
const String title = 'title_name_here';
final String address = 'address_here';
final painter = QrPainter.withQr(
qr: qrCode!,
color: const Color(0xFF000000),
gapless: true,
embeddedImageStyle: null,
embeddedImage: null,
);
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
final ts = DateTime.now().millisecondsSinceEpoch.toString();
String path = '$tempPath/$ts.png';
// ui is from import 'dart:ui' as ui;
final picData =
await painter.toImageData(2048, format: ui.ImageByteFormat.png);
// writeToFile is seen in code snippet below
await writeToFile(
picData!,
path,
);
} else {
genericErrorDialog(context);
}
// qrStorage is a reference to a folder in firebase storage
await qrStorage.child('name_here').putFile(qrFile);
var url =
await qrStorage.child('name_here').getDownloadURL();
late File qrFile;
Future<void> writeToFile(ByteData data, String path) async {
final buffer = data.buffer;
qrFile = await File(path).writeAsBytes(
buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
One solution is to use the screenshot package (https://pub.dev/packages/screenshot). This package has a function to save a widget as an image (without displaying it on screen) as shown below.
ScreenshotController screenshotController = ScreenshotController();
await screenshotController
.captureFromWidget(CustomWidget())
.then((capturedImage) async {
await do_something_with_capturedImage_here();
});
As it relates to my question specifically; Below is the code to generate a qr code, place it in a widget (needs some more formatting) with text, and then save the widget as an image file and upload to firebase.
String qrString = 'qr_data_here';
final qrValidationResult = QrValidator.validate(
data: qrString,
version: QrVersions.auto,
errorCorrectionLevel: QrErrorCorrectLevel.L,
);
if (qrValidationResult.status == QrValidationStatus.valid) {
final qrCode = qrValidationResult.qrCode;
const String title = 'title_name_here';
final String address = 'address_here';
final painter = QrPainter.withQr(
qr: qrCode!,
color: const Color(0xFF000000),
gapless: true,
embeddedImageStyle: null,
embeddedImage: null,
);
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
final ts = DateTime.now().millisecondsSinceEpoch.toString();
String path = '$tempPath/$ts.png';
// ui is from import 'dart:ui' as ui;
final picData =
await painter.toImageData(2048, format: ui.ImageByteFormat.png);
// writeToFile is seen in code snippet below
await writeToFile(
picData!,
path,
);
await screenshotController
.captureFromWidget(Column(
children: [
Text(title),
Image.file(qrFile),
Text(address),
],
))
.then((capturedImage) async {
await widgetToImageFile(capturedImage);
});
} else {
genericErrorDialog(context);
}
// qrStorage is a reference to a folder in firebase storage
await qrStorage.child('name_here').putFile(fullQrFile);
var url =
await qrStorage.child('name_here').getDownloadURL();
ScreenshotController screenshotController = ScreenshotController();
late File qrFile;
late File fullQrFile;
Future<void> writeToFile(ByteData data, String path) async {
final buffer = data.buffer;
qrFile = await File(path).writeAsBytes(
buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
Future<void> widgetToImageFile(
Uint8List capturedImage,
) async {
Directory newTempDir = await getTemporaryDirectory();
String newTempPath = newTempDir.path;
final newTs = DateTime.now().millisecondsSinceEpoch.toString();
String path = '$newTempPath/$newTs.png';
fullQrFile = await File(path).writeAsBytes(capturedImage);
}
I am working on an application that requires me to load pdf from url. The plugin I am using is syncfusion_flutter_pdf. I couldn't find a direct way to do the same so I tried downloading the file first and then use it. But the pdf is not displaying for some reason! There were nothing in the logs. Can you guys please tell me what went wrong?
fileDownload() async {
tempDir = await getApplicationDocumentsDirectory();
tempPath = tempDir.path + 'flutter-succinctly.pdf';
final dio = Dio();
if (await File(tempPath).exists()) {
//print('tempPath exists at: $tempPath');
if (await File(tempPath).length() == 0) {
dio.download(
'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf',
tempPath,
);
} else {
_readPDF();
}
} else {
print('path does not exist');
dio.download(
'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf',
tempPath);
}
}
Future<void> _readPDF() async {
final PdfDocument document =
PdfDocument(inputBytes: File(tempPath).readAsBytesSync());
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
child: const Text('Generate PDF'),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.lightBlue,
onSurface: Colors.grey,
),
onPressed: fileDownload,
)
],
),
));
}
We do not have direct support to load PDF from URL. We can load and read PDF data by using http package. We have created a sample to read the PDF data from webspace/website to load and save it using the retrieved PDF data. Kindly try the following code example and sample in your side,
Add http package in dependencies section of pubspec.yaml file
dependencies:
http: ^0.13.3
Import the following package in your dart file.
//Read an PDF data from website/webspace
import 'package:http/http.dart' show get;
Get image data
//Read an PDF data from website/webspace
var url = "https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf";
var response = await get(Uri.parse(url));
var data = response.bodyBytes;
Load data into PDF document
//Create a new PDF document
PdfDocument document = PdfDocument(inputBytes: data);
//Save PDF document
final List bytes = document.save();
//Dispose the document.
document.dispose();
Please find the sample from https://www.syncfusion.com/downloads/support/directtrac/general/ze/pdf_sample565926150.
I have a flutter E-commerce App which has a orderDetails page , I want to convert the whole page to pdf using flutter pdf package, as it would be more convinent because the data is retrived from FirebaseFirestore. Is there a way around I can achieve this ?
sub: I want to convert the whole flutter screen to pdf using this library
You can capture the screen using this package screenshot
then add that image to pdf document and save it
import 'dart:io';
import 'dart:typed_data';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart ' as pw;
Future getPdf(Uint8List screenShot) async {
pw.Document pdf = pw.Document();
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (context) {
return pw.Expanded(
child: pw.Image(PdfImage.file(pdf.document, bytes: screenShot), fit: pw.BoxFit.contain)
);
},
),
);
File pdfFile = File('Your path + File name');
pdfFile.writeAsBytesSync(pdf.save());
}
full details:
load dependencies in pubspec.yaml:
screenshot:
share_plus:
path_provider:
permission_handler:
import packages in your dart file:
import 'package:screenshot/screenshot.dart';
import 'package:share_plus/share_plus.dart';
import 'package:permission_handler/permission_handler.dart';
shareImage() async {
final uint8List = await screenshotController.capture();
String tempPath = (await getTemporaryDirectory()).path;
String fileName ="myFile";
if (await Permission.storage.request().isGranted) {
File file = await File('$tempPath/$fileName.png').create();
file.writeAsBytesSync(uint8List);
await Share.shareFiles([file.path]);
}
}
and call shareImage() on any place:
GestureDetector(
onTap: (){ shareImage();},
child: ........,
),
remember to wrap your desire widget in:
Screenshot(
controller: screenshotController,
child: Text("This text will be captured as image"),
),
newest solution will be
shareImage() async {
final uint8List = await screenshotController.capture();
String tempPath = (await getTemporaryDirectory()).path;
String fileName =" ";>>>>>your file name between ""
File file = await File('$tempPath/$fileName" }.png').create();
file.writeAsBytesSync(uint8List!);
await Share.shareFiles([file.path]);
}
import 'dart:io';
import 'dart:typed_data';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart ' as pw;
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
Future screenToPdf(String fileName,Uint8List screenShot) async {
pw.Document pdf = pw.Document();
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (context) {
return pw.Expanded(
child: pw.Image(pw.MemoryImage(screenShot), fit: pw.BoxFit.contain),
);
},
),
);
String path = (await getTemporaryDirectory()).path;
File pdfFile = await File('$path/$fileName.pdf').create();
pdfFile.writeAsBytesSync(await pdf.save());
await Share.shareFiles([pdfFile.path]);
}
Following code generates empty pdf, can you please point out the error
I am using dart pdf package https://pub.dev/packages/pdf. pdf is getting generated but content is empty.
adding tag flutter, if someone has used same package in flutter and may know answer.
import 'dart:io';
import 'package:pdf/pdf.dart';
main() {
try {
createPdf();
} catch (e) {
print(e);
}
}
void createPdf() async {
PdfDocument pdf = PdfDocument();
PdfPage page = PdfPage(pdf);
PdfImage image =
PdfImage.file(pdf, bytes: File('./test.jpg').readAsBytesSync());
final g = page.getGraphics();
g.drawImage(image, image.height.toDouble(), image.width.toDouble());
final file = File("./test.pdf");
await file.writeAsBytes(pdf.save());
}
You should use the widgets library:
import 'dart:io';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
void main() {
try {
createPdf();
} catch (e) {
print(e);
}
}
void createPdf() async {
final doc = Document();
final image = PdfImage.file(doc.document, bytes: File('./test.jpg').readAsBytesSync());
doc.addPage(
Page(
build: (context) => Center(child: Image(image)),
),
);
final file = File("./test.pdf");
await file.writeAsBytes(doc.save());
}