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;
});
}
Related
I am currently a developing an application in MVC Core that is using a PDFTron webviewer. Is there anyway to save the edited pdf edited with pdftron webviewer to the server?
There is a feature of pdftron that saves annotations to the server, but I need to save the whole pdf with the edits to the server.
WebViewer({
path: '/lib/WebViewer',
initialDoc: '/StaticResource/Music.pdf', fullAPI: !0, enableRedaction: !0
}, document.getElementById('viewer')).then(
function(t) {
samplesSetup(t);
var n = t.docViewer;
n.on('documentLoaded', function() {
document.getElementById('apply-redactions').onclick = function() {
t.showWarningMessage({
title: 'Apply redaction?',
message: 'This action will permanently remove all items selected for redaction. It cannot be undone.',
onConfirm: function () {
alert( );
t.docViewer.getAnnotationManager().applyRedactions()
debugger
var options = {
xfdfString: n.getAnnotationManager().exportAnnotations()
};
var doc = n.getDocument();
const data = doc.getFileData(options);
const arr = new Uint8Array(data);
const blob = new Blob([arr], { type: 'application/pdf' });
const data = new FormData();
data.append('mydoc.pdf', blob, 'mydoc.pdf');
// depending on the server, 'FormData' might not be required and can just send the Blob directly
const req = new XMLHttpRequest();
req.open("POST", '/DocumentRedaction/SaveFileOnServer', true);
req.onload = function (oEvent) {
// Uploaded.
};
req.send(data);
return Promise.resolve();
},
});
};
}),
t.setToolbarGroup('toolbarGroup-Edit'),
t.setToolMode('AnnotationCreateRedaction');
}
);
When i send the request to the Controller i am not getting the file it is coming null
[HttpPost]
public IActionResult SaveFileOnServer(IFormFile file)
{
return Json(new { Result="ok"});
}
Can any one suggest me where i am going wrong
Thanks in adavance
For JavaScript async function, you need to wait for it completes before doing other things. For example, AnnotationManager#applyRedactions() returns a Promise, the same for AnnotationManager#exportAnnotations() and Document#getFileData().
For JS async functions, you can take a look at:
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Promises
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
So here you may want to use await to wait for the Promise completes.
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);
}
}
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;}
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 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);
});