Unable to load pdf from url using Syncfusion_flutter_pdf - flutter

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.

Related

uploading An Image to Database using MultiPartFile in Flutter

I want to upload an image that I have already retrieved from the database(product table) to the cart table.
The issue is, I can't use the .path with the MultipartFile("file", image.path);
I am getting an error if I try using .path with my image variable. I've also tried several methods but none is working... I'll attach my codes below
The image is already stored in a map(revievedMap) which I receivr from the previous screen so I'm not using an imagePicker, the product image I'm trying to access is already stored in the database.
request.fields['image'] = "http://10.0.2.2:/shopice/assets/${args.product.image}";
request.fields['image'] = "http://localhost:/shopice/assets/${args.product.image}";
I tried the code above, obviously didn't work.
var pic = await http.MultipartFile.fromPath("image", args.product.image!);
//request.files.add(pic);
I also tried this, but I need to set the path on the second argument, but args.product.image.path(), is returning this error
[the getter 'path' isn't defined for the type 'String'. (Documentation) Try importing the library that defines 'path', correcting the name to the name of an existing getter, or defining a getter or field named 'path'.]
here is the code:
//args.receivedMap: is my buyer detials
//args.product: is the product i'm trying to add to cart, which //contains the image
args.seller: is the seller details
child: FlatButton(
onPressed: ()async {
if(!args.receivedMap.isEmpty){
final uri = Uri.parse("http://10.0.2.2:/shopice/api/buyer/addToCart");
var request = http.MultipartRequest('POST', uri);
request.fields['buyer_id'] =args.receivedMap['id'];
request.fields['seller_id'] = args.seller.id.toString();
request.fields['seller_name'] = args.seller.name!;
request.fields['buyer_name'] = args.receivedMap['name'];
request.fields['price'] = args.product.pricePerKg!;
request.fields['product_name'] = args.product.name!;
//request.fields['image'] = "http://10.0.2.2:/shopice/assets/${args.product.image}";
//var pic = await http.MultipartFile.fromPath("image", "http://localhost:/shopice/assets/${args.product.image}");
//File file = "http://10.0.2.2:/shopice/assets/${args.product.image}" as File;
//var pic = await http.MultipartFile.fromString("image", args.product.image!);
//request.files.add(pic);
var bytes = (await rootBundle.load('http://localhost/shopice/assets/${args.product.image}')).buffer.asUint8List();
var mpFile = http.MultipartFile.fromBytes('img', bytes);
request.files.add(mpFile);
var response = await request.send();
print(args.product.image);
if (response.statusCode == 200) {
showModalBottomSheet(context: context, builder: (context){
return Wrap(children: [ListTile(leading: Icon(Icons.done_outline), title: Text('Product Added TO Cart'),)],);
});
}
else if (response.statusCode == 500) {
showModalBottomSheet(context: context, builder: (context){
return Wrap(children: [ListTile(leading: Icon(Icons.done_outline), title: Text('Server Error '),)],);
});
}
else {
showModalBottomSheet(context: context, builder: (context){
return Wrap(children: [ListTile(leading: Icon(Icons.done_outline), title: Text('ERROR WHILE PERFORMING OPPERATION\n CONTACT SUPPORT'),)],);
});
}
}
else if(args.receivedMap.isEmpty){
var snackbar = SnackBar(
content: Text('Login To Add Product To Cart!',
style: TextStyle(fontSize: 16.0)),
backgroundColor:
const Color(0xff4A777A),
padding: EdgeInsets.only(left: 50.0),
);
ScaffoldMessenger.of(context)
.showSnackBar(snackbar);
}
},
child: Text(
'Add to Cart',
style: GoogleFonts.poppins(
color: Color(0xff4A777A)),
)),
i simply add the image from the backend and forget about doing it with flutter, i moved the image with php and did some trial and error which later worked

Send image picker file to the backend

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.

Flutter Firestore Collection to PDF

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');

open pdf file from assets flutter

I am trying to open PDF file using flutter_fullpdfview 1.0.12, i have the PDF file located under assets folder but somehow i am getting error unable to find file. I tried several options but none of them worked all return same error. Below are the functions i tried to load file and both of them failed with same error.
Future<File> copyAsset() async {
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
File tempFile = File('$tempPath/copy.pdf');
ByteData bd = await rootBundle.load('assets/jainaarti.pdf');
await tempFile.writeAsBytes(bd.buffer.asUint8List(), flush: true);
return tempFile;
}
Future<File> fromAsset(String asset, String filename) async {
// To open from assets, you can copy them to the app storage folder, and the access them "locally"
Completer<File> completer = Completer();
try {
var dir = await getApplicationDocumentsDirectory();
File file = File("${dir.path}/$filename");
var data = await rootBundle.load(asset);
var bytes = data.buffer.asUint8List();
await file.writeAsBytes(bytes, flush: true);
completer.complete(file);
} catch (e) {
throw Exception('Error parsing asset file!');
}
return completer.future;
}
It appears that the pdf library you are using is set up to use a system filepath to load the pdf. Unfortunately, this differs from the asset path that you have access to, and Flutter currently does not support the ability to get an assets system filepath at runtime. The only way I can find to use that library is to transfer the files to a known directory, and load from there. Rather than do this, I would recommend the native_pdf_view library, as it supports asset loading as well as full screen. You should be able to implement it as follows:
final pdfController = PdfController(
document: PdfDocument.openAsset('assets/copy.pdf'),
);
return Scaffold(
body: Center(
child: PdfView(
controller: pdfController,
)
),
);
-- EDIT --
To switch pages, if you want to start the viewer on a different page, just edit the initialPage in the pdfController
final pdfController = PdfController(
document: PdfDocument.openAsset('assets/copy.pdf'),
initialPage: 2
);
If you want to switch pages after the pdfView has been created, you can call jumpToPage() or animateToPage() from anywhere, provided you can get a reference to the pdfController, and that it and the pdfView have been instantiated.
return Scaffold(
body: Stack(
children: [
Center(
child: PdfView(
controller: pdfController,
)
),
RaisedButton(
child: Text("Page 2"),
onPressed: (){
pdfController.jumpToPage(2);
// -- or --
pdfController.animateToPage(2, duration: Duration(seconds: 1), curve: Curves.linear);
},
),
],
),
);

Flutter Dio : How to Upload Image?

I'm trying on Postman. And it works
I want upload some image to rest-api using Package DIO Package ,
I'm new for this package (i'm use this package just for CRUD operation) and i'm got problem when upload image operation.
i'm already reading documentation and nothing see for upload images. I'm try this code(ref on documentation) and got some error :
error:FileSystemException
message :"Cannot retrieve length of file"
OSError (OS Error: No such file or directory, errno = 2)
"File: '/storage/emulated/0/Android/data/com.example.mosque/files/Pictures/scaled_IMG_20190815_183541.jpg'"
Type (FileSystemException)
message:FileSystemException: Cannot retrieve length of file, path = 'File: '/storage/emulated/0/Android/data/com.example.mosque/files/Pictures/scaled_IMG_20190815_183541.jpg'' (OS Error: No such file or directory, errno = 2)
DioErrorType (DioErrorType.DEFAULT)
name:"DioErrorType.DEFAULT"
Api.dart
Future uploadImage({dynamic data,Options options}) async{
Response apiRespon = await dio.post('$baseURL/mahasiswa/upload/',data: data,options: options);
if(apiRespon.statusCode== 201){
return apiRespon.statusCode==201;
}else{
print('errr');
return null;
}
}
View.dart
void uploadImage() async {
FormData formData = FormData.from({
"name_image": _txtNameImage.text,
"image": UploadFileInfo(File("$_image"), "image.jpg")
});
bool upload =
await api.uploadImage(data: formData, options: CrudComponent.options);
upload ? print('success') : print('fail');
}
_image is type FILE
I hope who expert with this package can help me with this code and suggest me for upload images.
Thanks.
Full View.dart Code
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mosque/api/api_mosque.dart';
class UploadImage extends StatefulWidget {
#override
_UploadImageState createState() => _UploadImageState();
}
class _UploadImageState extends State<UploadImage> {
ApiHelper api = ApiHelper();
File _image;
TextEditingController _txtNameImage = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_left),
onPressed: () => Navigator.pop(context, false),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.file_upload),
onPressed: () {
uploadImage();
},
)
],
),
body: _formUpload(),
);
}
Widget _formUpload() {
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: <Widget>[
TextField(
controller: _txtNameImage,
keyboardType: TextInputType.text,
decoration: InputDecoration(hintText: "Nama Image"),
maxLength: 9,
textAlign: TextAlign.center,
),
SizedBox(
height: 50.0,
),
Container(
child: _image == null
? Text('No Images Selected')
: Image.file(_image),
),
SizedBox(
height: 50.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Icon(Icons.camera),
onPressed: () => getImageCamera(),
),
SizedBox(
width: 50.0,
),
RaisedButton(
child: Icon(Icons.image),
onPressed: () => getImageGallery(),
)
],
)
],
),
);
}
void uploadImage() async {
FormData formData = FormData.from({
"name_image": _txtNameImage.text,
"image": UploadFileInfo(File("$_image"), "image.jpg")
});
bool upload =
await api.uploadImage(data: formData, options: CrudComponent.options);
upload ? print('success') : print('fail');
}
getImageGallery() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = imageFile;
});
}
getImageCamera() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_image = imageFile;
});
}
}
In Dio latest version, UploadFileInfo method has been replaced by MultipartFile class. And here the way how to use to post image, video or any file:
Future<String> uploadImage(File file) async {
String fileName = file.path.split('/').last;
FormData formData = FormData.fromMap({
"file":
await MultipartFile.fromFile(file.path, filename:fileName),
});
response = await dio.post("/info", data: formData);
return response.data['id'];
}
Even this question is asked a while ago, I believe the main issue is the size of image especially with Laravel.Flutter Image Picker library offers some functionalities to reduce the size of Image, I solved it with bellow steps:
Create a method to get the Image, I am using Camera to Capture the photo
Future getImage() async {
File _image;
final picker = ImagePicker();
var _pickedFile = await picker.getImage(
source: ImageSource.camera,
imageQuality: 50, // <- Reduce Image quality
maxHeight: 500, // <- reduce the image size
maxWidth: 500);
_image = _pickedFile.path;
_upload(_image);
}
Create _upload method to upload the photo, I am using Dio package Dio Package
void _upload(File file) async {
String fileName = file.path.split('/').last;
FormData data = FormData.fromMap({
"file": await MultipartFile.fromFile(
file.path,
filename: fileName,
),
});
Dio dio = new Dio();
dio.post("http://192.168.43.225/api/media", data: data)
.then((response) => print(response))
.catchError((error) => print(error));
}
On the server side, I am using Laravel Laravel, I handle the request as follow
public function store(Request $request)
{
$file = $request->file('file');
$extension = $file->getClientOriginalExtension();
$fullFileName = time(). '.'. $extension;
$file->storeAs('uploads', $fullFileName, ['disk' => 'local']);
return 'uploaded Successfully';
}
In the latest version of Dio :
It should look like this.
String fileName = imageFile.path.split('/').last;
FormData formData = FormData.fromMap({
"image-param-name": await MultipartFile.fromFile(
imageFile.path,
filename: fileName,
contentType: new MediaType("image", "jpeg"), //important
),
});
If without this line.
contentType: new MediaType("image", "jpeg")
Maybe it will cause an error: DioError [DioErrorType.RESPONSE]: Http status error [400] Exception
And get MediaType in this package: http_parser
The following code uploads multiple image files from a dio client to a golang server.
dioclient.dart
FormData formData = FormData.fromMap({
"name": "wendux",
"age": 25,
"other" : "params",
});
for (File item in yourFileList)
formData.files.addAll([
MapEntry("image_files", await MultipartFile.fromFile(item.path)),
]);
Dio dio = new Dio()..options.baseUrl = "http://serverURL:port";
dio.post("/uploadFile", data: formData).then((response) {
print(response);
}).catchError((error) => print(error));
golangServer.go
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func uploadFile(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(200000)
if err != nil {
fmt.Fprintln(w, err)
return
}
formdata := r.MultipartForm
files := formdata.File["image_files"]
for i, _ := range files {
file, err := files[i].Open()
defer file.Close()
if err != nil {
fmt.Fprintln(w, err)
return
}
out, err := os.Create("/path/to/dir/" + files[i].Filename)
defer out.Close()
if err != nil {
fmt.Fprintf(w, "Unable to create the file for writing. Check your write access privilege")
return
}
_, err = io.Copy(out, file)
if err != nil {
fmt.Fprintln(w, err)
return
}
fmt.Fprintf(w, "Files uploaded successfully : ")
fmt.Fprintf(w, files[i].Filename+"\n")
}
}
func startServer() {
http.HandleFunc("/uploadFile", uploadFile)
http.ListenAndServe(":9983", nil)
}
func main() {
fmt.Println("Server starts!")
startServer()
}
I have found a solution, where I am uploading file a specific directory which is generated different camera package which requires file path to save jpg file in the provided path.
and I was fetching file name with path and passing to
DIO package
which was giving file length issue, to I have implemented below steps to solve the issue
get File Name With Full Path from directory
create a File from the Path
File(directoryFilePathWithExtension);
and pass File.path to the dio package
MultipartFile.fromFile(
File(directoryFilePathWithExtension).path,
filename: DateTime.now().toIso8601String(),
)
Use UploadFileInfo.fromBytes if you're working with memory images (The error message above shows that your file is invalid and doesn't exist).
Hi there are many issue in file upload
try in android Api 21 because it did not have android permissions if api is working in android api 21 then it wil also work on above versions.
you might not able to get the file in above android version
you just need
FormData formData = FormData.fromMap({
"av_document": await MultipartFile.fromFile(_filePath,filename:
_fileName),
});
to upload any file or image to server and one more thing to note
_filePaths = await FilePicker.getMultiFilePath(type: _pickingType,
fileExtension: _extension);
_fileName = _filePath.split('/').last
by using this process u can upload file or image to server
I am using
dio: ^4.0.6 (for uploading)
flutter_native_image: ^0.0.6+1 (for reducing image size)
to reduce file size
File? compressedFile = profileImage.value == null
? null
: await FlutterNativeImage.compressImage(
profileImage.value?.path ?? '',
quality: 20,
percentage: 60);
dio formData map
var formData = dio.FormData.fromMap({
"name": input['name']!.text,
"profile_pic": await dio.MultipartFile.fromFile(compressedFile.path),
"birth_date": input['dob']!.text,})
request ->
response = await _dio.post(url, data: formData);