I am using the react-native-share extension for the share and print Pdf document. I am trying to add The 'Print' attribute but it is not working or I couldn't get it right
I follow this document https://react-native-community.github.io/react-native-share/docs/share-open#activitytype
and i used the example here https://react-native-community.github.io/react-native-share/docs/share-open#activityitemsources-ios-only
According to this document, I created an object like
const url = this.props.navigation.state.params.document.url
{
item:{
print : url
}
},
https://react-native-community.github.io/react-native-share/docs/share-remote-file
The code below solves my problem for IOS. I think there was a problem because the document came from the url.Its still not working for android
static sharePDFWithAndroid(fileUrl, type) {
let filePath = null;
let file_url_length = fileUrl.length;
const configOptions = { fileCache: true };
RNFetchBlob.config(configOptions)
.fetch('GET', fileUrl)
.then(resp => {
filePath = resp.path();
return resp.readFile('base64');
})
.then(async base64Data => {
base64Data = `data:${type};base64,` + base64Data;
await Share.open({ url: base64Data });
// remove the image or pdf from device's storage
await RNFS.unlink(filePath);
});
}
Related
I'm trying to save a base64 encoded image in iOS using react-native-share and also Share module from React Native. But both fail when trying the Save Image option.
React Native Share
try {
const sharedResponse = await Share.open({ url: dataUri });
console.log(sharedRes);
} catch (error) {
console.log(error);
}
Share Module
try {
const sharedResponse = await Share.share({ url: dataUri });
console.log(sharedRes);
} catch (error) {
console.log(error);
}
Options other than Save image such as copy, and save to files are working fine.
I have added the following in Info.plist as well
<key>NSPhotoLibraryAddUsageDescription</key>
<string>APP wants to save to photos</string>
This is working fine on the first try in the app's lifetime (When it's asking the permissions from the user). After that this functionality doesn't work.
For some reason you need to write the file to the temp directory first before sharing. I'm not sure the reasoning behind this... but it did fix the issue for me.
const filename = `snapshot.jpeg`; // or some other way to generate filename
const filepath = `${FileSystem.cacheDirectory}/${filename}`;
await FileSystem.writeAsStringAsync(filepath, res.data, { encoding: 'base64' });
const isSharingAvailable = await isAvailableAsync();
if (!isSharingAvailable) {
showAlert('Error', 'Sharing is not available.')
return;
}
if (Platform.OS === 'ios') {
//sharing just the file allows for more applications to be shared too. Adding a message seems to remove many apps from the sharing list
await Share.share({ url: filepath });
}
This strange behaviour had happened because I'm trying to open the Share pop-up above a React Native Modal. The issue didn't occur if I try to hide the Modal before the Share pop-up comes up.
I resolved the issue when storing the image locally before opening the Share Modal.
To store the image i used the npm package 'react-native-fs' and then use it just like this:
import RNFS from "react-native-fs";
function storeFileLocally(url: string): Promise<string> {
const localFile = `${RNFS.DocumentDirectoryPath}/tempFile.jpeg`;
const options: RNFS.DownloadFileOptions = {
fromUrl: url,
toFile: localFile
};
return RNFS.copyFile(url, localFile)
.then(() => 'file://'+localFile)
.catch((error) => {
console.error(error);
return null;
});
}
I'm trying to upload image from React native(without expo) (on Android OS only) to a post endpoint in ASP.net core web API.
In my react native app, I have used 'react-native-image-picker' to capture the image using camera like below.
launchCamera(options, (response: ImagePickerResponse) => {
console.log('Response = ', response);
if (response.assets) {
setVehicle({
...vehicle,
image: {
name: response.assets[0].fileName,
uri: response.assets[0].uri,
type: response.assets[0].type,
},
});
}
});
Once I have the image details is my vehicle state, I'm adding it to form data and doing axios post call like below.
const data = new FormData();
data.append('image', {
name: vehicle.image.name,
uri: vehicle.image.uri,
type: vehicle.image.type,
});
axios.post('https://localhost:44343/api/vehicle', data, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
My post endpoint in ASP.net core web api looks like this.
[Route("")]
[HttpPost]
public IActionResult Post([FromForm(Name = "image")]IFormFile image)
{
//Upload the image to blob storage
}
The image argument variable always contains null value in this endpoint, I tried many think but couldn't fix this. Can anyone help me?😞
Finally found a way to upload images. Not sure if this is the ideal way, but this the only way I could make it work.
After getting the image URI of captured image, I fetched the blob for the image.
const image = await fetch(vehicleImageURI);
const blob = await image.blob();
const fileReaderInstance = new FileReader();
fileReaderInstance.readAsDataURL(blob);
fileReaderInstance.onload = () => {
const base64data = fileReaderInstance.result;
postVehicle({ ...vehicle, base64Image: base64data as string })
.then((res) => {
console.log(res);
})
.catch((ex) => {
console.log(ex);
});
};
On the API side I removed the IFormFile and FromForm from post endpoint and removed the base64image as string.
[Route("")]
[HttpPost]
public IActionResult Post(string image)
{
Regex regex = new Regex(#"^[\w/\:.-]+;base64,");
var base64File = regex.Replace(data.Base64Image, string.Empty);
byte[] imageBytes = Convert.FromBase64String(base64File);
MemoryStream stream = new MemoryStream(imageBytes, 0, imageBytes.Length);
}
Please let us known if you know a better way to do this!🤞
I have an Ionic 3 App where I can upload picture from a device. This feature works well with IOS, but fail on Android with the error code 5 (Encoding error).
This is the flow :
protected takePicture(source: number, callback: any) {
const options: CameraOptions = {
sourceType: source,
mediaType: 2,
};
this.camera.getPicture(options).then((imageData) => {
return callback(imageData)
});
}
And then :
let promise = new Promise((resolve, reject) => {
let prefix = '';
if (i.indexOf('file://') === -1 && i !== '') {
prefix = 'file://';
}
this.file.resolveLocalFilesystemUrl(prefix + i).then((fileEntry: any) => {
fileEntry.file((file: any) => {
let reader = new FileReader();
if (file.size > 99999999) {
return this.events.publish('error', this.errorUploadMessage, false);
}
reader.onloadend = function(e) {
let blob = new Blob([this.result], { type: file.type });
let filename = file.name;
let extension = filename.match(/^.*\./);
if (!extension || extension === '') {
let type = file.type.split('/').pop();
filename = filename + '.' + type;
}
resolve({ blob: blob, name: filename });
};
reader.readAsArrayBuffer(file);
});
}, (error) => {
console.log(error);
this.events.publish('error', this.errorUploadMessage, false);
});
});
Everything work well with IOS so I don't understand why not with android. When I check the path here:
this.file.resolveLocalFilesystemUrl(prefix + i)
I have this :
file://content://com.android.providers.media.documents/document/image%3A1313
Maybe the problem comes from 'image%3A1313' at the end. On IOS I can se the real picture name and extension (.jpeg for exemple).
I already checked several issues on SOF, but nothing work or seems to be revelant to my issue.
Ok just found the solution... removing the prefix ("file://") seems to do the trick... It's strange because I never seen this suggestion anywhere..
I'm working on an ionic3 application. I need to take an image from the user either by camera or gallery, first saves it to the local directory then upload the image to the server. I used the following step by step tutorial: https://devdactic.com/ionic-2-images/
Uploading the photo is working like a charm, but while saving the image to the local directory and save the path on local storage, after retrieving from storage it shows the following error: .
As it's obvious it complains about Not allowed to load local resource.
Next, I started to google for the solution, and I found this solution in StackOverflow and this in GitHub. As they both suggested, the problem is with cordova-plugin-ionic-webview, so I need to downgrade the version. When I tried their solution, the uploading and showing the image to the user is working perfectly, however, it creates problem other parts of the application which is loading data from asset no matter what; images, fonts. Shows the following error .Next I found a solutionf for the problem in GitHub here, as it suggested and accepted by most users we need to use the latest version of **cordova-plugin-ionic-webview **, which of course it would cause the first problem for me.
I'm gonna upload the codes here as well.`
getImage() {
this.presentActionSheet();
} //end getImage
public uploadImage() {
console.log('Uploading the image');
console.log(this.lastImageL);
var targetPath = this.pathForImage(this.lastImage);
console.log(targetPath);
var url = "https://dev.raihan.pomdev.net/wp-json/raihan/v1/profilePhoto";
var filename = this.lastImage;
console.log(' targetPath : ', targetPath);
console.log('File Name : ', filename)
console.log(url, " IS the URL");
var options = {
fileKey: "image",
fileName: filename,
chunkedMode: false,
mimeType: "multipart/form-data",
params: {
'image': filename,
'user_id': 79
}
};
const fileTransfer: TransferObject = this.transfer.create();
this.loading = this.loadingCtrl.create({
content: 'منتظر باشید',
});
this.loading.present();
// Use the FileTransfer to upload the image
fileTransfer.upload(targetPath, url, options).then(data => {
this.loading.dismissAll()
this.presentToast(' . عکس شما موفقانه ذخیره شد');
this.storage.set("Profile_Photo", targetPath).then((data) => {
console.log('response of uploading the image ', data);
console.log('Target Path ', targetPath);
console.log('In set storage ', targetPath);
$("#Photo").attr("src", targetPath);
$("#Photo2").attr("src", targetPath);
console.log('myphoto ', targetPath);
});
}, err => {
this.loading.dismissAll()
this.presentToast('مشکلی در قسمت ذخیره کردن عکس شما وجود دارد ' + err);
console.log('error sending the image');
console.log(err);
});
}
public takePicture(sourceType) {
var options = {
quality: 100,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
// Get the data of an image
this.camera.getPicture(options).then((imagePath) => {
if (this.platform.is('android') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {
this.filePath.resolveNativePath(imagePath)
.then(filePath => {
let correctPath = filePath.substr(0, filePath.lastIndexOf('/') + 1);
let currentName = imagePath.substring(imagePath.lastIndexOf('/') + 1, imagePath.lastIndexOf('?'));
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
});
} else {
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
}
}, (err) => {
this.presentToast('Error while selecting image.');
});
}
ionViewDidLoad() {
console.log('ionViewDidLoad CaptureImagePage');
}
private createFileName() {
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
return newFileName;
}
// Copy the image to a local folder
private copyFileToLocalDir(namePath, currentName, newFileName) {
this.file.copyFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(success => {
this.lastImage = newFileName;
this.uploadImage();
}, error => {
this.presentToast('Error while storing file. ' + error);
});
}
private presentToast(text) {
let toast = this.toastCtrl.create({
message: text,
duration: 5000,
position: 'center'
});
toast.present();
}
// Always get the accurate path to your apps folder
public pathForImage(img) {
if (img === null) {
return '';
} else {
return cordova.file.dataDirectory + img;
}
}
public presentActionSheet() {
let actionSheet = this.actionSheetCtrl.create({
title: 'Select Image Source',
buttons: [
{
text: 'Load from Library',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
}
},
{
text: 'Use Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
actionSheet.present();
}
`
Now I'm confused which version of **cordova-plugin-ionic-webview ** I should use? Is there someone who could help me?
Note: Thanks for your patience to read all the questions.
I would try to use the latest version of the WebView if possible, and then use the window.Ionic.WebView.convertFileSrc() method on the file:/// path before putting it on a page for display. Those tips can be seen here:
https://ionicframework.com/docs/building/webview
Cordova and Capacitor apps are hosted on a local HTTP server and are
served with the http:// protocol. Some plugins, however, attempt to
access device files via the file:// protocol. To avoid difficulties
between http:// and file://, paths to device files must be rewritten
to use the local HTTP server. For example, file:///path/to/device/file
must be rewritten as http://://path/to/device/file
before being rendered in the app.
For Cordova apps, the Ionic Web View plugin provides a utility
function for converting File URIs:
window.Ionic.WebView.convertFileSrc(). There is also a corresponding
Ionic Native plugin: #ionic-native/ionic-webview.
Here is a sample method I use, which works fine in the 4.x webview:
getNormalizedUrl(path: string): SafeResourceUrl {
let newPath = this.domSanitizer.bypassSecurityTrustUrl(
window.Ionic.WebView.convertFileSrc(path));
return newPath;
}
Question is simple, I would like to open any pdf or doc file via default App with using Flutter.
Think a Raised button that related my pdf asset, when user press it, pdf will be opened via Acrobat reader or etc. I don't want to use any web_view for it.
is it supported in Flutter?
A good and simple approach to this is the open_file package which lets you open a file with the given path. It supports numerous different file types.
UPDATE July 2022:
As the open_file package has some permissions in the manifest that are not allowed anymore for Store uploads there is a fork of this (open_filex) package that has this permission removed. The usage is the same:
import 'package:open_filex/open_filex.dart';
OpenFile.open("/sdcard/example.pdf");
You can do this by opening google docs in a web browser :
In pubspec.yaml you need :
url_launcher: ^0.4.2+5
Includes :
import 'package:flutter/src/gestures/tap.dart';
import 'package:url_launcher/url_launcher.dart';
Code snippet :
new RichText(
text: new LinkTextSpan(
url: 'http://docs.google.com/viewer?url=http://www.pdf995.com/samples/pdf.pdf',
text: 'Show My Pdf'),
),
LinkTextSpan class :
class LinkTextSpan extends TextSpan {
LinkTextSpan({TextStyle style, String url, String text})
: super(
style: style,
text: text ?? url,
recognizer: new TapGestureRecognizer()
..onTap = () {
launch(url);
});
}
without downloading file,open from URL using the package
: url_launcher
import 'package:url_launcher/url_launcher.dart';
_launchURL() async {
const url = 'https://flutter.dev/exapmle.pdf';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
You can use [ flutter_full_pdf_viewer 1.0.6 ] Dependencie
You can use url_launcher package for this. Just pass the path of your document to the launch() method as the parameter.
class EmployeeViewModel {
EmployeeModel _employeeModel = EmployeeModel();
String fname;
void downloadFile(BuildContext context, String fileUrl, String fileName, ProgressListener listener) async {
String _filePath = '';
if (Platform.isAndroid) {
String _directory = await ExtStorage.getExternalStoragePublicDirectory(ExtStorage.DIRECTORY_DOWNLOADS);
print(_directory);
_filePath = '$_directory/$fileName';
//todo getting file name here
print("file name" + fileName);
fname = fileName;
print("file fname" + fname);
//APIKey.FILE_NAME: fileName;
} else if (Platform.isIOS) {
Directory _directory = await getApplicationDocumentsDirectory();
_filePath = '${_directory.path}/$fileName';
print("file name" + fileName);
//log(fileName);
debugPrint(_directory.path);
print("directory path" + _directory.path);
}
var response = await Dio().downloadUri(Uri().resolve(fileUrl), _filePath);
if (response.statusCode == 200) {
listener.isProcessing(false);
AlertMessageDialog(context, UtilString.downloadCompleted, UtilString.downloadCompletedMessage, UtilString.open, AlertMessageDialogActionHandler());
} else {
listener.isProcessing(false);
UtilAction.showSnackBar(context, response.statusMessage);
}
} class AlertMessageDialogActionHandler implements AlertMessageDialogListener {
#override
Future<void> onPositiveButtonClick() async {
String _filePath = '';
String fileName;
String _directory = await ExtStorage.getExternalStoragePublicDirectory(ExtStorage.DIRECTORY_DOWNLOADS);
//todo geeting right directory path here
print("directory" + _directory);
_filePath = '$_directory/$fileName';
print("file path" + _filePath);
// print("filename" + fileName);
OpenFile.open("/storage/emulated/0/Download/GA55-Estimated-SHRIGOPAL-VERMA-2020-2021.pdf"); }}