Flutter: save a generated PDF from preview page with a custom function - flutter

I'm using the pdf package (link to pub.dev page) to create documents inside my app.
How can I save the document from the preview page?
I know about the built-in print and share functions, but I need something else.
I need a function that does the following:
save the document to the device
upload it to Firebase Storage
delete the local file
I know how to do all of these steps, but I'm unable to access the Uint8List bytes of the pdf document that is being previewed... I've tried to add a PdfPreviewAction, but I still can't access the bytes of the document from it

all you have to do is call the save method in the Document() object
import "package:pdf/widgets.dart" as w;
final pdf = w.Document();
Future<Uint8List> getPDFData() async {
return await pdf.save();
}
you can do all the operations using the getPDFData() method
for example:
return PdfPreview(
build: (format) => getPdfData(),
actions: [
PdfPreviewAction(
icon: Icon(Icons.print),
onPressed: (context, fn, format) {
//if you call fn(format), you'll get Future<UInt8List>
}),
],
);

Related

How to retrieve an image from Firestore database - Flutter

i was wondering how to retrieve an image from Firestore, i was trying and reading and watching tutorials so i have come with this solution:
1- Upload images to Firebase storage.
2- Go to Firestore create a collection and a document with field name and value of image path. ( collection "majorChallenges", doc "challenge-1", field "source", value "image path url")
3- Initiate a Firestore Instance: var _fireStoreInstance = FirebaseFirestore.instance;
4- Access the Database collection using QuerySnapshot: QuerySnapshot qn = await _fireStoreInstance.collection("majorChallenges").get();
5- now after that am not sure how to setState, initState, return and display the image inside Scaffold or Container.
some tutorials are using the image link or name which is not efficient for me what if i have to change the image in the future so the best solution i believe must not use the image name it should access the collection and the doc and retrieve the image path.
i already set up the read and write permissions and i have accessed the database before to retrieve text so no authorisation problems, I would be very thankful if someone could complete the steps for us
I can now answer my own question, first of all it is wrong to specify this operation in steps because there are a lot of approaches to achieve this goal, and the approach i am using is pretty nice and simple using QuerySnapshot. so to retrieve picture we need simply do these steps (for my approach):
1- we need to declare a string variable then create asynchronous method that will fetch the image URL from Firestore and update the variable state using set state method, inside this method we can initiate a Firestore instance and a QuerySnapshot:
String img = "";
fetchMajorChallengeImage() async {
var _fireStoreInstance = FirebaseFirestore.instance;
QuerySnapshot qn =
await _fireStoreInstance.collection("majorChallenges").get();
setState(() {
img = qn.docs[0]["source"];
});
return qn.docs;
}
2- we will initiate the state using initState method and call our function inside:
void initState() {
fetchMajorChallengeImage();
super.initState();
}
3- now the image is retrieved and the path stored to "img" variable we declared, so we need to display the image, here its your choice where and how to display the image but for me this is how i displayed it:
Widget build(BuildContext context) {
return InkWell(
onTap: () {},
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Image.network(img, height: 150, fit: BoxFit.fill),
],
),
);
}
note that it must be displayed inside Image.network() widget because the variable holds a URL value fetched from the firestore collection > doc > value and now the image is retrieved and displayed successfully.

CREATE INVOICE PDF using FLUTTER WEB

I need to create a path to temporarily store my pdf file before sharing it. but path_provider does not support web. please what other way can i use to share the pdf decuments.
knowing that I want to create an incoice.
here is the context with some code
Future getPdf(Uint8List screenShot) async {
pw.Document pdf = pw.Document();
final img = pw.MemoryImage(screenShot);
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (context) {
return pw.Expanded(
child: pw.Image(img),
);
},
),
);
// File pdfFile = File('Your path + File name');
// pdfFile.writeAsBytesSync(await pdf.save());
print(pdf);
}
in this specific case I would like to use an alternative to path_provider

Flutter how to check if pdf print data has been delivered

I made an app that converts images to datr-pdf and prints them. my app prints in Wi-Fi Direct format and uses the printing package. there is no problem in printing using the default print service in both android and IOS. select a printer from the default print service and press the print button after connecting, data is sent to the printer and the app returns to the previous app screen from the default print service screen.
After sending data to the printer, I want to receive a return about success or failure with a bool variable in the process of returning to the previous screen.
My end goal is to pass data from the app to the printer and when I return to the screen of the app, if return is `true', I want the app to close while printing. I'm looking at the source via 'GitHub' but haven't found it yet. Do you know of a method or class that sends data and returns to the app's screen??
My PrintSource
_generatedPdf(PdfPageFormat format, BuildContext context) async {
final pdf = pdfWidget.Document(version: PdfVersion.pdf_1_5, compress: true);
//Page Num
for(int nCount=0; nCount<context.read<ScoreImageProvider>().scoreImageList.length; nCount++){
final image = await imageFromAssetBundle(context.read<ScoreImageProvider>().scoreImageList[nCount]);
pdf.addPage(
pdfWidget.Page(
pageFormat: format,
build: (pdfWidget.Context context){
return pdfWidget.Center(
child: pdfWidget.Padding(
padding: pdfWidget.EdgeInsets.zero,
child: pdfWidget.Image(image, fit: pdfWidget.BoxFit.fill)
)
);
}
)
);
}
bool bRes = await Printing.layoutPdf(onLayout: (format) async => pdf.save());
}
printing package verseion is printing: ^5.6.6 thank you.
Solved
Check if printing is complete in void onCompleted in PrintingHandler.java file.

type 'Future<File>' is not a subtype of type 'File'

Important: I have searched a lot but did not find any solution that I can understand.
I am using photo manager to show images and then after selecting an image I want to navigate to the next screen and show that image there (later I want to upload that image to firebase storage).
So the type of File I am getting from the photo_manager package is Future < File > and I am receiving File from the second screen.
How can I convert future to file?
First Screen:
IconButton(
icon: const Icon(Icons.arrow_forward, color: primaryColor),
onPressed: () {
Get.to(PostDetail(
imgFile:
_controller.mediaList[_controller.selectedImageIndex].file,
));
},
),
Second Screen:
On the second screen, I'm getting File.
final File imgFile;
const PostDetail({this.imgFile});
Source Code:: Add Post Page
So as described in photo_manager docs, you need to get the file from the AssetEntity list before moving to the next page.
So on button pressed to go to next page get the file and then pass it to the Page
Below code should work:
IconButton(
icon: const Icon(Icons.arrow_forward, color: primaryColor),
onPressed: () async {
File file = await _controller.mediaList[_controller.selectedImageIndex].file; // image file
Get.to(PostDetail(
imgFile: file,
));
},
),
File and Future<File> are 2 different things. the File is a variable that its value is in the present. but Future<File> as its name suggests, its value exist in the Future which means its value takes some time to reach you.
for example, if you send a request to a webserver, the response takes some time to reach you. so, in that case the response is a Future.
in your case the image you are trying to get is supplied in a way that it takes time. to get the File from Future<File> you have to wait. So before sending the file to this Screen, use an async and wait to turn the Future<File> to File. (i dont know how you get the file)
for example,
File myFile = await getFileorWhaterver();
Your _controller.mediaList[_controller.selectedImageIndex].file is a Future<File> means that the value of the File is promised to be returned sometimes in the future. This usually because you are doing a network call asynchronously to get the data from API.
In order to convert it to File, you need to await till the moment that value is available. However you cannot do an async/await within the UI, that's why Flutter provide a widget named FutureBuilder to wait for a certain Future value, then let you use that value in the UI.
In your case, you can do this:
FutureBuilder(
future: _controller.mediaList[_controller.selectedImageIndex].file,
builder: (context, snapshot) {
return IconButton(
icon: const Icon(Icons.arrow_forward, color: primaryColor),
onPressed: () {
if (snapshot.hasData)
Get.to(PostDetail(imgFile: snapshot.data));
},
);
})

How do i save a generated PDF to Accessible storage?

I did generated a pdf from HTML code , using html_to_pdf pluggin ,
but it seems that it saves it in DocumentAppPath (data/user/0/com.exmpl.myapp/app_flutter/) which is not something easy to access by a user whom does not know much .
Future<void> generateExampleDocument() async {
var htmlContent = widget.htmlCont; // html Cv File's content
Directory appDocDir = await getApplicationDocumentsDirectory(); // appDocDir
var targetPath = appDocDir.path;
var targetFileName = "example-pdf";
var generatedPdfFile = await FlutterHtmlToPdf.convertFromHtmlContent(
htmlContent, targetPath, targetFileName); // generates pdf document at the given path.
generatedPdfFilePath = generatedPdfFile.path; // variable outside function .
}
then displaying the pdf , it works fine However as i said i want it to be saved somewhere where the user access it for example Download folder .. so after i can simply Open it from that path outside my app .
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PDFViewerScaffold(
appBar: AppBar(title: Text("SHOW TEST")),
path: generatedPdfFilePath)),
),
),
Thanks.
I've used esys_flutter_share package. I had same task, but I was generating pdf from the widget using pdf package. So then I've add save button, wich calls share function with options to save the file on mobile or send it someone else.
final sharePdf = await generatedPdfFile.readAsBytes();
await Share.file(
'PDF Document',
'project.pdf',
sharePdf.buffer.asUint8List(),
'*/*',
);