I am trying to generate Pdf in flutter with pdf package in flutter Web.
while doing so I found a solution for flutter web with this code ..
Uint8List bytes = await pdf.save() ;
final blob = html.Blob([bytes], 'application/pdf');
final url = html.Url.createObjectUrlFromBlob(blob);
html.window.open(url, "_blank");
html.Url.revokeObjectUrl(url);
this code worked fine in local host but is not running in web hosting . please help
My first answer was deleted, so I'll repost it.
To download files look this one:
https://stackoverflow.com/a/60614367/18386517.
If you want to just open PDFs files inside your app try the pdfx package. Here is an example:
import 'dart:async';
import 'dart:typed_data';
import 'package:pdfx/pdfx.dart';
import 'package:flutter/material.dart';
class PdfLabPage extends StatefulWidget {
final String name;
final FutureOr<Uint8List> content;
const PdfLabPage({Key? key, required this.name, required this.content}) : super(key: key);
#override
State<PdfLabPage> createState() => _PdfLabPageState();
}
class _PdfLabPageState extends State<PdfLabPage> {
late PdfControllerPinch pdfController;
#override
void initState() {
pdfController = PdfControllerPinch(
document: PdfDocument.openData(widget.content)
);
super.initState();
}
#override
void dispose() {
pdfController.dispose();
super.dispose();
}
Widget pdfView() => PdfViewPinch(
controller: pdfController ,
onDocumentLoaded: (msg) {print(msg.toString());},
onDocumentError: (error) { print(error.toString());}
);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.name),
),
body:
Center(
child: pdfView(),
),
);
}
}
I got the content of the PDF file from the web using:
var url = "..."
final file = await http.get(Uri.parse(url));
final content = file.bodyBytes;
But you can load from assets (Android, Ios, MacOs, Web):
final document = await PdfDocument.openAsset('assets/sample.pdf')
From file (Android, Ios, MacOs):
final document = await PdfDocument.openFile('path/to/file/on/device')
From data (Android, Ios, MacOs, Web):
final document = await PdfDocument.openData((FutureOr<Uint8List>) data)
Related
I list all pptx files from storage now I want to display these files inside my app using a file path. I used different packages like power file view, flutter file reader. but engine load failed all time so i need a material related opening pptx files inside my flutter app
Add this in your pubspec.yaml
pdftron_flutter:
git:
url: git://github.com/PDFTron/pdftron-flutter.git
main.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:pdftron_flutter/pdftron_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _version = 'Unknown';
#override
void initState() {
super.initState();
initPlatformState();
PdftronFlutter.openDocument("https://pdftron.s3.amazonaws.com/downloads/pdfref.pdf");
}
// Platform messages are asynchronous, so we initialize via an async method.
Future<void> initPlatformState() async {
String version;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
PdftronFlutter.initialize();
version = await PdftronFlutter.version;
} on PlatformException {
version = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_version = version;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('PDFTron flutter app'),
),
body: Center(
child: Text('Running on: $_version\n'),
),
),
);
}
}
For more help read this blog
TLDR: I understand how to create a new file via Dart and path provider, but I don't know how to get a pre-existing file into the Android/Apple file system.
I'm building this app which works a bit with string manipulation. Ideally, I want it reading strings from a pre-existing CSV file which I'm getting from a client, then manipulating the data to create more CSV files. I found packages for both CSV and Paths. What I don't know is how to get my CSV in there.
As of now I have this file called test.csv in my app's root directory. I tried to access it through my main.dart by using File f = File("$_localPath/test.csv"). The file was nowhere to be found. I then went into the phone's memory using Android Studio, and found the local storage path of the app. My test.csv file was nowhere to be seen. My guess right now is that at compilation, that CSV file becomes garbage machine code. So how can I get it intact into the device's local memory?
I don't want to get the file from the internet because I'm hoping the user can boot up the app for the first time in any setting and be able to have its full functionality.
I just tested this code example and it works on all platforms.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _fileContent = '';
final TextEditingController _controller = TextEditingController();
#override
initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
readFile();
});
}
Future<String> getFilePath() async {
Directory appDocumentsDirectory =
await getApplicationDocumentsDirectory(); // 1
String appDocumentsPath = appDocumentsDirectory.path;
String filePath = '$appDocumentsPath/file.csv';
return filePath;
}
void saveFile() async {
File file = File(await getFilePath());
if (mounted) {
file.writeAsString(_controller.text);
setState(() {
_fileContent = _controller.text;
});
_controller.text = '';
}
}
void readFile() async {
File file = File(await getFilePath());
final fileContent = await file.readAsString();
if (mounted) {
setState(() {
_fileContent = fileContent;
});
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Saving CSV file')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text('Current content = $_fileContent'),
TextField(
controller: _controller,
),
TextButton(
onPressed: saveFile,
child: const Text('Press to save file'),
),
],
),
),
),
);
}
}
This code creates the file and sets a content into it. Then, after restarting the app, it tries to find the file and receive its content. After that it shows the content inside a Text widget.
I used this article for making this example. Hope it will help:)
I'm trying to download an image from the network and save it locally in the Downloads folder of a computer. I need to achieve that for flutter web, I'm not sure how to do it.
I found some questions related to how to achieve download and save a file or an image for android and IOS, such as Flutter save a network image to local directory. I also took a look at How do I read and write image file locally for Flutter Web?. However, I don't see how those answers can help me.
I think that for IOS and Flutter I can use the following function without getting any error, but I don't know where the files are being saved in my emulator:
void _downloadAndSavePhoto() async {
var response = await http.get(Uri.parse(imageUrl));
try {
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
File file = File('$tempPath/$name.jpeg');
file.writeAsBytesSync(response.bodyBytes);
} catch (e) {
print(e.toString());
}
}
However, when I try the above function for flutter web (using a chrome simulator) I get the following error:
MissingPluginException(No implementation found for method getTemporaryDirectory on channel plugins.flutter.io/path_provider)
I will be more than happy if someone knows a way to do it or have some suggestions to implement that functionality.
Thanks in advance!
To achieve this I would suggest you first to add the universal_html package to your pubspec.yaml because in the newer versions of Flutter you will get warnings for importing dart:html.
In pubspec.yaml:
dependencies:
flutter:
sdk: flutter
http: ^0.13.1 // add http
universal_html: ^2.0.8 // add universal_html
I created a fully working example Flutter web app, you can try it, but the only thing that interests you is the downloadImage function.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
// if you don't add universal_html to your dependencies you should
// write import 'dart:html' as html; instead
import 'package:universal_html/html.dart' as html;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final imageUrls = <String>[
'https://images.pexels.com/photos/208745/pexels-photo-208745.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
'https://images.pexels.com/photos/1470707/pexels-photo-1470707.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
'https://images.pexels.com/photos/2671089/pexels-photo-2671089.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
'https://images.pexels.com/photos/2670273/pexels-photo-2670273.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.count(
crossAxisCount: 3,
children: imageUrls
.map(
(imageUrl) => ImageCard(imageUrl: imageUrl),
)
.toList(),
),
);
}
}
class ImageCard extends StatefulWidget {
#override
_ImageCardState createState() => _ImageCardState();
final String imageUrl;
ImageCard({
#required this.imageUrl,
});
}
class _ImageCardState extends State<ImageCard> {
Future<void> downloadImage(String imageUrl) async {
try {
// first we make a request to the url like you did
// in the android and ios version
final http.Response r = await http.get(
Uri.parse(imageUrl),
);
// we get the bytes from the body
final data = r.bodyBytes;
// and encode them to base64
final base64data = base64Encode(data);
// then we create and AnchorElement with the html package
final a = html.AnchorElement(href: 'data:image/jpeg;base64,$base64data');
// set the name of the file we want the image to get
// downloaded to
a.download = 'download.jpg';
// and we click the AnchorElement which downloads the image
a.click();
// finally we remove the AnchorElement
a.remove();
} catch (e) {
print(e);
}
}
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () => downloadImage(widget.imageUrl),
child: Card(
child: Image.network(
widget.imageUrl,
fit: BoxFit.cover,
),
),
);
}
}
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);
},
)
));
}
}
I had tried but it doesn't load pdf file. This is My Code
import 'package:flutter/material.dart';
import 'package:flutter_plugin_pdf_viewer/flutter_plugin_pdf_viewer.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool _isLoading = true;
PDFDocument document;
#override
void initState() {
super.initState();
loadDocument();
}
loadDocument() async {
document = await PDFDocument.fromUrl('https://drive.google.com/drive/u/0/folders/1ei6916qmZ34LZECNf5e0DlvB7EJqxqz8');
setState(() => _isLoading = false);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('PDF FILE'),
),
body: Center(`enter code here`
child: _isLoading
? Center(child: CircularProgressIndicator())
: PDFViewer(document: document)),
),
);
}
}
It seems like the id in your link (https://drive.google.com/drive/u/0/folders/1ei6916qmZ34LZECNf5e0DlvB7EJqxqz8) is a folder id.
To get your link, open the file
in a new window and copy the Url into your code.
If the link doesn't work, try the following link format in which you insert the file Id from the Url you got previously.
https://drive.google.com/file/d/fileId/
For this you need to be autenticated user of Google.
And after successfully login
Use these api to ge the drive data:
https://www.googleapis.com/drive/v2/files
and also you need to pass the token over the header with Authorization key:
"Authorization" = "Bearer " + token
or simply you can create a public link of your file, than copy url and use it.