Flutter Web: Converting dart:io File to dart:html File - dart

Is there a way to convert dart:io File object to dart:html File? I tried html.File file = dartFile as html.File and it isn't working

No. The two file objects are completely unrelated.
I am not aware of any platform which has both the dart:io and the dart:html library available, so even being able to import both in the same program is surprising.

No way. But you can handle it by having different code. See bellow:
final _photos = <File>[];
final _photosWeb = <html.File>[];
if (kIsWeb == false) { //if its not web, handle dart.io file
final pickedFile = await _picker.getImage(
source: ImageSource.gallery,
imageQuality:
100,
);
File image = File(pickedFile!.path);
if (image != null) {
_photos.insert(_numberOfImage, image);
}
} else { //if its web, handle html.file
final temp = (await ImagePicker()
.getImage(source: ImageSource.camera, imageQuality: 80));
final pickedFile = await temp!.readAsBytes();
var image = html.File(temp.path.codeUnits, temp.path);
if (image != null) {
_photosWeb.insert(_numberOfImage, image);
}
}

Related

How to convert pdf to text in Flutter?

I want to read user given PDF file. Convert it into text. But it should work both on android and iOS.
This is a complex topic and I can only give you hints.
There are no dart libraries for this. You can either implement it natively on iOS/Android and use platform channels to communicate with the native code, or use an online service for the conversion.
For example, you can use Ghostscript in Firebase Cloud Functions. Ghostscript is capable of pdf to text conversion.
How to extract text with Ghostscript
How to use Ghostscript in Firebase Cloud Functions
How to use Firebase Cloud Functions in Flutter
Try "pdf_text" plugin. You can convert pdf to text using this plugin.
/// Picks a new PDF document from the device
Future _pickPDFText() async {
File file = await FilePicker.getFile();
_pdfDoc = await PDFDoc.fromFile(file);
setState(() {});
}
/// Reads a random page of the document
Future _readRandomPage() async {
if (_pdfDoc == null) {
return;
}
setState(() {
_buttonsEnabled = false;
});
String text =
await _pdfDoc.pageAt(Random().nextInt(_pdfDoc.length) + 1).text;
setState(() {
_text = text;
_buttonsEnabled = true;
});
}
/// Reads the whole document
Future _readWholeDoc() async {
if (_pdfDoc == null) {
return;
}
setState(() {
_buttonsEnabled = false;
});
String text = await _pdfDoc.text;
setState(() {
_text = text;
_buttonsEnabled = true;
});
}

Saving image file then uploading sometimes not working

So, I am trying to save an image file from the camera then upload it to firebase. Unfortunately, the firebase storage plugin has some errors and doesn't return errors in the catch so I need to check wifi connection before i do so, just in case i need to cache the image and upload it later. Once the image file has uploaded i then create some JSON and send that to firebase database where the app pulls down relevant information.
Note: sometimes this code works and the image is not empty, othertimes the image comesback empty so im guessing its a timing issue?
Future saveImageFile(UploadImage image) async {
await storage.init();
var imageFile = storage.saveImageFile(image.file, image.getName());
instance.setInt("ImageCount", imageCount + 1);
checkConnectionThenUploadImage(imageFile);
}
//From storage class
File saveImageFile(File toBeSaved, String fileName) {
final filePath = '$imageDirectory$fileName';
var file = new File(filePath)
..createSync(recursive: true)
..writeAsBytes(toBeSaved.readAsBytesSync());
return file;
}
checkConnectionThenUploadImage(File image) {
checkConnectivity().then((isConnected) async {
if (!isConnected) {
instance.setBool("hasImagesToUpload", true);
} else {
await saveImageToStorage(image);
}
}).catchError((error) {
print("Error getting connectivity status, was error: $error");
});
}
saveImageToStorage(File imageFile) async {
final fileName = getNameFromFile(imageFile);
final StorageReference ref = FirebaseStorage.instance.ref().child("AllUsers").child(uuid).child(fileName);
final StorageUploadTask uploadTask = ref.putFile(imageFile, const StorageMetadata(contentLanguage: "en"));
final url = (await uploadTask.future).downloadUrl;
if (url != null) { //Normally you could catch an error here but the plugin has a bug so it needs to be checked in other ways
final fireImage = new FireImage(getNameFromFile(imageFile), storage.getDateFromFileName(fileName), imageCount, "", url.toString());
saveImageJsonToDatabase(fireImage);
storage.deleteImageFile(fileName);
} else {
checkConnectionThenUploadImage(imageFile);
}
}
saveImageJsonToDatabase(FireImage image) async {
await storage.init();
storage.saveJsonFile(image);
checkConnectivity().then((isConnected) {
if (!isConnected) {
instance.setBool("hasJsonToUpload", true);
} else {
final DatabaseReference dataBaseReference = FirebaseDatabase.instance.reference().child("AllUsers").child(uuid);
dataBaseReference.child("images").push().set(image.toJson()).whenComplete (() {
storage.deleteJsonFile(basename(image.name));
}).catchError((error) { //catching errors works with firebase database
saveImageJsonToDatabase(image);
});
}
});
}
//From storage class
deleteImageFile(String fileName) async {
final filePath = '$imageDirectory$fileName';
File(filePath).delete();
}
The image gets uploaded and the json is created but when i try to view the image using the download url from firebase storage it says the image is empty. The only clue i have is that this is a timing issue because it only happens occasionally.
Can anyone see where im going wrong?

How to get all PDF files from internal as well as external storage in Flutter?

I want to show All pdf files present in internal as well as external storage, So on tapping that particular file, i want to open that file in full screen dialog.
So in order to do that you need to:
Grant access to external storage in a directory where there are your PDF file. Let's call that folder <external storage>/pdf.
List all file of that directory a display them to the user.
Open the selected file with an application that can visualize PDF.
In order to do all that thinks I suggest you to use those flutter packages:
path_provider
simple_permission
With path_provider you can get the external storage directory of an Android device.
Directory extDir = await getExternalStorageDirectory();
String pdfPath = extDir + "/pdf/";
In order to access external storage you need to set this permission request in the ApplicationManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You could also only use READ_EXTERNAL_STORAGE but then the simple_permission plugin won't work.
With the simple_permission plugin then you go and ask user to be granted external storage access:
bool externalStoragePermissionOkay = false;
_checkPermissions() async {
if (Platform.isAndroid) {
SimplePermissions
.checkPermission(Permission.WriteExternalStorage)
.then((checkOkay) {
if (!checkOkay) {
SimplePermissions
.requestPermission(Permission.WriteExternalStorage)
.then((okDone) {
if (okDone) {
debugPrint("${okDone}");
setState(() {
externalStoragePermissionOkay = okDone;
debugPrint('Refresh UI');
});
}
});
} else {
setState(() {
externalStoragePermissionOkay = checkOkay;
});
}
});
}
}
Once we have been granted external storage access we an list our PDF directory:
List<FileSystemEntity> _files;
_files = dir.listSync(recursive: true, followLinks: false);
And show them in a ListView:
return new ListView.builder(
padding: const EdgeInsets.all(16.0),
itemCount: _files.length,
itemBuilder: (context, i) {
return _buildRow(_files.elementAt(i).path);
});
Than you have to open them with a viewer when the user tap on them.
To do that there isn't an easy way, because with Android we need to build a ContentUri and give access to this URI to the exteranl application viewer.
So we do that in Android and we use flutter platform channels to call the Android native code.
Dart:
static const platform =
const MethodChannel('it.versionestabile.flutterapp000001/pdfViewer');
var args = {'url': fileName};
platform.invokeMethod('viewPdf', args);
Native Java Code:
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "it.versionestabile.flutterapp000001/pdfViewer";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
#Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
if (call.method.equals("viewPdf")) {
if (call.hasArgument("url")) {
String url = call.argument("url");
File file = new File(url);
//*
Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
file);
//*/
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(photoURI,"application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(target);
result.success(null);
}
} else {
result.notImplemented();
}
}
});
}
}
And after all we can have our PDF list and viewable on Android.
You have a lot to study. I hope this could be an useful playground for you.
This is for External Storage, but you can get Also the Internal and Temporary directory and act similarly as here.
If you wanna do the same thing on iOS you need to create the same Native Code pdfViewer also on iOS project. Refer alway to flutter platform channels in order to do it. And remember that the external storage doesn't exists on iOS devices. So you could use only the application sandbox document folder or the temporary one.
GitHub repo.
Happy coding.
i use this code for list files and directories
Future<List<FileSystemEntity>> dirContents(Directory dir) {
var files = <FileSystemEntity>[];
var completer = Completer<List<FileSystemEntity>>();
var lister = dir.list(recursive: false);
lister.listen((file) async {
FileStat f = file.statSync();
if (f.type == FileSystemEntityType.directory) {
await dirContents(Directory(file.uri.toFilePath()));
} else if (f.type == FileSystemEntityType.file && file.path.endsWith('.pdf')) {
_files.add(file);
}
}, onDone: () {
completer.complete(files);
setState(() {
//
});
});
return completer.future;
}
Directory dir = Directory('/storage/emulated/0');
var files = await dirContents(dir);
print(files);
Here is my code to list files from the download folder
List<dynamic> filesList = [];
Future listDir() async {
Directory dir = Directory(
'/storage/emulated/0/Download');
await for (FileSystemEntity entity
in dir.list(recursive: true, followLinks: false)) {
FileSystemEntityType type = await FileSystemEntity.type(entity.path);
if (type == FileSystemEntityType.file &&
entity.path.endsWith('.pdf')) {
filesList.add(entity.path);
}
}
return filesList;}

PCLStorage and binary data

I'm just new in this PCL libraries, I'm developing an iPhone app with Xamarin and I can't find the way to save it on the phone. The closest I get is with PCLStorage but he only saves text.
There is another way that I can save binary files with other procedure.
Thank you.
foreach (images element in json_object)
{
//var nameFile = Path.Combine (directoryname, element.name);
try{
IFile file = await folder_new.GetFileAsync(element.name);
}catch(FileNotFoundException ex ){
RestClient _Client = new RestClient(element.root);
RestRequest request_file = new RestRequest("/images/{FileName}");
request_file.AddParameter("FileName", element.name, ParameterType.UrlSegment);
_Client.ExecuteAsync<MemoryStream>(
request_file,
async Response =>
{
if (Response != null)
{
IFolder rootFolder_new = FileSystem.Current.LocalStorage;
IFile file_new = await rootFolder_new.CreateFileAsync(element.name,CreationCollisionOption.ReplaceExisting);
await file_new.WriteAllTextAsync(Response.Data);
}
});
}
}
Use the IFile.OpenAsync method to get a stream which you can use to read/write binary data. Here's how you would read a file:
IFile file = await folder_new.GetFileAsync(element.name);
using (Stream stream = await file.OpenAsync(FileAccess.Read))
{
// Read stream and process binary data from it...
}

How does one 'read' a file from a Dart VM program?

How does one 'read' a file from a Dart program ?
http://api.dartlang.org/index.html
Dart would be running on the client-side and so taking files as input should be allowed.
You can find a usage of files in Dart's testing framework:
status_file_parser.dart (search for 'File').
In short:
File file = new File(path);
if (!file.existsSync()) <handle missing file>;
InputStream file_stream = file.openInputStream();
StringInputStream lines = new StringInputStream(file_stream);
lines.lineHandler = () {
String line;
while ((line = lines.readLine()) != null) {
...
};
lines.closeHandler = () {
...
};
Note that the API is not yet finalized and could change at any moment.
Edit: API has changed. See Introduction to new IO
Your question implies you want to do this from the client-side, that is, the browser. The dart:io library only works in the stand-alone VM on the command line.
If you do want to read a file from within the VM, there's now an easier way:
import 'dart:io';
main() {
var filename = new Options().script;
var file = new File(filename);
if (!file.existsSync()) {
print("File $filename does not exist");
return;
}
var contents = file.readAsStringSync();
print(contents);
}
If you do not want to block while the whole file is read, you can use the async version of readAsString which returns a Future:
file.readAsString().then((contents) {
print(contents);
});

Resources