Share custom file using React Native - android

I have a custom file something like file.myext which I create it using rn-fetch-blob:
RNFetchBlob.fs.writeFile(path, JSON.stringify(data), 'utf8')
And I'm using react-native-share to share the file,
I tried both:
Share.open({type: 'text/plain', url: 'file://'+path})
and
RNFetchBlob.fs.readFile(path, 'base64')
.then((data) => {
Share.open({url: 'data:text/plain;base64,'+data})
})
but doesn't work, the second one share .txt file.
anyway to solve this?

Might help, when I was also looking into this, using react-native-fs I was able to do:
var path = RNFS.DocumentDirectoryPath + '/test.txt';
RNFS.writeFile(path, 'test', 'utf8')
.then(() => {
console.log('FILE WRITTEN!');
Share.open({
url: 'file://' + path,
})
.then(res => {
console.log(res);
})
.catch(err => {
err && console.log(err);
});
})
.catch(err => {
console.log(err.message);
});

Related

react-native-fs path not found?

import RNFS from 'react-native-fs';
var path = RNFS.DocumentDirectoryPath + '/test.txt';
RNFS.writeFile(path, 'Lorem ipsum dolor sit amet', 'utf8')
.then(success => {
console.log('FILE WRITTEN!');
})
.catch(err => {
console.log(err.message);
});
console.log(RNFS.DocumentDirectoryPath)
// /data/data/xxx.xxx.xxx/files/
But I didn't find a path/file like /data/xxx.xxx.xxx/files/ in the data directory of the mobile phone
But the entry in the code exists
RNFS.readDir(RNFS.DocumentDirectoryPath).then(result => {
console.log('DocumentDirectoryPath GOT RESULT', result);
});
I want to know what is the path of RNFS.DocumentDirectoryPath in the phone?
Try This Way
RNFS.readDir(RNFS.DocumentDirectoryPath)
.then((result) => {
console.log('GOT RESULT', result);
})
First you need to Check the file is existing or not
const filePath = RNFS.DocumentDirectoryPath + "/test" + ".txt";
RNFS.exists(filePath)
.then(success => {
if (success) {
readFile(filePath, logData);
} else {
writeFile(filePath, logData);
}
})
.catch(err => {
console.log(err.message, err.code);
});
const readFile = (filePath, logData) => {
RNFS.readFile(filePath, "utf8")
.then(content => {
// Do what you need if the file exists
})
.catch(err => {
console.log(err.message, err.code);
});
};
const writeFile = (filePath, logData) => {
RNFS.writeFile(filePath, logData, "utf8")
.then(() => {
// This will create new file for you in the name of test.txt
})
.catch(err => {
console.log(err.message, err.code);
});
};
For finding files in the mobile storage. You should have to use External Directory Path
Document's directory path could be found in the android emulator.
[path- Device Explorer/'Your Package name 'eg: 'com.'/data/files/you
have your file ]

Unable to load files from an old version of an app after recompiling it

There is the following problem in my React Native app. The app stored some PDF files as files and was able to access them. Then probably after recompilation the app started having problems accessing those files. However, the files are still there. I downloaded the app's full data container to check.
I have a suspicion it is because there is a dynamic part of the app's data container URI that always changes after recompilation followed by the actual path? e.g. D22506C1-9364-43A4-B3C7-F9FFF0E1CC48, 6BDC3F93-6BC3-4BB6-BD3F-9BFA7E4A4627
If so, what is the best practice to store URIs in React Native in database so they can be retrieved again?
The following 6 PDF files:
ListViewItem.js:30 Debug: Report URI /var/mobile/Containers/Data/Application/D22506C1-9364-43A4-B3C7-F9FFF0E1CC48/Documents/Reports/dk79lqddh3mlkcstqel9.pdf
ListViewItem.js:30 Debug: Report URI /var/mobile/Containers/Data/Application/D22506C1-9364-43A4-B3C7-F9FFF0E1CC48/Documents/Reports/e1exw1qg4cs6czktrfkfvi.pdf
ListViewItem.js:30 Debug: Report URI /var/mobile/Containers/Data/Application/D22506C1-9364-43A4-B3C7-F9FFF0E1CC48/Documents/Reports/zfy6hp3zf42me5ru32jfa.pdf
ListViewItem.js:30 Debug: Report URI /var/mobile/Containers/Data/Application/D22506C1-9364-43A4-B3C7-F9FFF0E1CC48/Documents/Reports/fum4qf23mwnzcmye39xau.pdf
ListViewItem.js:30 Debug: Report URI /var/mobile/Containers/Data/Application/D22506C1-9364-43A4-B3C7-F9FFF0E1CC48/Documents/Reports/btksznt1lxv7k4ey23bw93.pdf
ListViewItem.js:30 Debug: Report URI /var/mobile/Containers/Data/Application/6BDC3F93-6BC3-4BB6-BD3F-9BFA7E4A4627/Documents/Reports/smpkiggii4v7xmfhpnmdi.pdf
URIs as those can't be loaded at different places of the app:
Example 1
<Pdf style={styles.image} source={{ uri: 'file://' + this.props.pdf }} />
Example 2
FileService.readFileFromStorage('file://' + this.report.report_uri, 'base64')
static readFileFromStorage(path, encoding) {
return new Promise((resolve, reject) => {
RNFS.readFile(path, encoding)
.then((file) => {
resolve(file);
})
.catch((err) => {
console.log('Error: unable to read file', path, err.message);
reject(err)
});
})
}
This was used to write the files:
FileService.writeFiletoStorage(r.taskId, 'pdf', base64Str)
static writeFiletoStorage(fileName, extention, base64Str) {
return new Promise((resolve, reject) => {
RNFS.mkdir(RNFS.DocumentDirectoryPath + '/Reports')
var path = RNFS.DocumentDirectoryPath + '/Reports/' + fileName + '.' + extention;
return RNFS.writeFile(path, base64Str, 'base64')
.then((success) => {
console.log('FILE WRITTEN!', path, success);
resolve(path);
})
.catch((err) => {
console.log('Error: unable to write file to storage', path, err.message);
reject(err)
});
})
}
The method to write file was returning the full path, which varies across different compilations. Returning just the relative path works better:
static writeFiletoStorage(fileName, extension, base64Str) {
return new Promise((resolve, reject) => {
RNFS.mkdir(RNFS.DocumentDirectoryPath + 'Reports')
let path = '/Reports/' + fileName + '.' + extension;
let fullPath = RNFS.DocumentDirectoryPath + path;
return RNFS.writeFile(fullPath, base64Str, 'base64')
.then((success) => {
console.log('FILE WRITTEN!', fullPath, success);
resolve(path);
})
.catch((err) => {
console.log('Error: unable to write file to storage', fullPath, err.message);
reject(err)
});
})
}
Same change had to be made for method to read file:
static readFileFromStorage(path, encoding) {
return new Promise((resolve, reject) => {
let fullPath = RNFS.DocumentDirectoryPath + path;
RNFS.readFile(fullPath, encoding)
.then((file) => {
resolve(file);
})
.catch((err) => {
console.log('Error: unable to read file', fullPath, err.message);
reject(err)
});
})
}

firebase dynamic link with react-navigation

I have followed this document https://rnfirebase.io/docs/v4.1.x/links/android and able to run adb shell am start -W -a android.intent.action.VIEW -d "https://abc123.app.goo.gl" com.myapp.superapp to start the app.
How can open a dynamic link https://abc123.app.goo.gl it open the VideoScreen and pass the contentparam
Video:{
screen : VideoScreen,
path:'wvc/:contentparam',
}
So I tried this when clicking https://abc123.app.goo.gl (dynamic link):
componentDidMount () {
Linking.getInitialURL().then((url) => {
console.log('Initial url is: ' + url);
}).catch(err => console.error('An error occurred', err));
}
However app opened but console.log given null
For some reason firebase.links().onLink((url) does not work in RNFB v6.
Here is a comment on this bug from one of RNFB maintainers
https://github.com/invertase/react-native-firebase/issues/3008
Use should use react native Link instead, as a temporary workaround:
https://facebook.github.io/react-native/docs/0.47/linking
Here is an example you can use:
useEffect(() => {
Linking.getInitialURL()
.then(url => {
if (url) {
console.log('Initial url is: ' + group);
}
})
.catch(err => console.error('An error occurred', err));
}, []);
You have to listen to firebase links
componentDidMount() {
const unsubscribe = firebase.links().onLink((url) => {
console.log('dynamic links', url)
// do navigate with url above
// you have to handle your self
});
}
componentWillUnmount() {
unsubscribe()
}
docs: https://rnfirebase.io/docs/v5.x.x/links/reference/links#onLink

Saving file to Downloads directory using Ionic 3

i know this link: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/#where-to-store-files
but i would like to save the file in Downloads directory. Is this possible to save the file in any path using Ionic? If so, please, share the example.
Here's the code:
downloadImage(image) {
this.platform.ready().then(() => {
const fileTransfer: TransferObject = this.transfer.create();
const imageLocation = `${cordova.file.applicationDirectory}www/assets/img/${image}`;
fileTransfer.download(imageLocation, cordova.file.externalDataDirectory + image).then((entry) => {
const alertSuccess = this.alertCtrl.create({
title: `Download Succeeded!`,
subTitle: `${image} was successfully downloaded to: ${entry.toURL()}`,
buttons: ['Ok']
});
alertSuccess.present();
}, (error) => {
const alertFailure = this.alertCtrl.create({
title: `Download Failed!`,
subTitle: `${image} was not successfully downloaded. Error code: ${error.code}`,
buttons: ['Ok']
});
alertFailure.present();
});
});
}
Basically I want save the file in location that is visible to the user.
the problem was lack of permission. Here is the working code that can download file to downloads directory:
async downloadFile() {
await this.fileTransfer.download("https://cdn.pixabay.com/photo/2017/01/06/23/21/soap-bubble-1959327_960_720.jpg", this.file.externalRootDirectory +
'/Download/' + "soap-bubble-1959327_960_720.jpg");
}
getPermission() {
this.androidPermissions.hasPermission(this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE)
.then(status => {
if (status.hasPermission) {
this.downloadFile();
}
else {
this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE)
.then(status => {
if(status.hasPermission) {
this.downloadFile();
}
});
}
});
}
To download the File to the Download directory you need to use Cordova File and FileTransfer Plugins.
import { File } from '#ionic-native/file';
import { FileTransfer } from '#ionic-native/file-transfer';
constructor(private transfer: FileTransfer) { }
fileTransfer: FileTransferObject = this.transfer.create();
//Use your File Url and name
downloadFile(file) {
// Some Loading
this.fileTransfer.download(url, this.file.externalRootDirectory +
'/Download/' + file).then(response => {
console.log(response);
this.dismissLoading();
this.presentToast('File has been downloaded to the Downloads folder. View
it..')
})
.catch(err => {
this.dismissLoading();
console.log(err)
});
}
Hope it helps.
import { File } from '#ionic-native/file';
import { FileTransfer } from '#ionic-native/file-transfer';
constructor(private file: File, private transfer: FileTransfer){}
let link = 'url_to_download_file';
let path = '';
let dir_name = 'Download'; // directory to download - you can also create new directory
let file_name = 'file.txt'; //any file name you like
const fileTransfer: FileTransferObject = this.transfer.create();
let result = this.file.createDir(this.file.externalRootDirectory, dir_name, true);
result.then((resp) => {
path = resp.toURL();
console.log(path);
fileTransfer.download(link, path + file_name).then((entry) => {
console.log('download complete: ' + entry.toURL());
}, (error) => {
console.log(error)
});
}, (err) => {
console.log('error on creating path : ' + err);
});
I know this is late, but I've always had issues with the FileTransfer plugin. Maybe it is just me. I've instead had success with the writeFile() method of the File plugin.
I'm still working on iOS, but for Android here is what I have:
import { File } from "#ionic-native/file";
constructor(private fileSystem: File) {}
Then, in whatever function you have the logic to save the file, we have:
let path = this.fileSystem.externalRootDirectory + '/Download/'; // for Android
let filename = 'myNewFile.pdf';
this.fileSystem.writeFile(path, filename, File, { replace: true }).then(() => {
this.toastCtrl.showToast('File has been downloaded. Please check your downloads folder.');
}, (err) => {
alert("Sorry. An error occurred downloading the file: " + err);
}
);
As I said, I'm still looking out for what path to use for iOS. And I'm still wondering how to pop up the notification that usually comes up when a download actually goes to the download folder. But at least I am able to save directly in the download folder of Android.
This code - ionic 3 capacitor - from josh morony takes a photo from the tmp directory and writes to the Document directory in this section using the FileSystem API the retrieves and manipulates the path
Filesystem.writeFile({
data: result.data,
path: fileName,
directory: FilesystemDirectory.Data
})
getFromPhotos() {
let options = {
resultType: CameraResultType.Uri
};
Camera.getPhoto(options).then(
(photo) => {
Filesystem.readFile({
path: photo.path
}).then((result) => {
// let date = new Date(),
// time = date.getTime(),
time = 'bilder',
fileName = time + '.jpeg';
Filesystem.writeFile({
data: result.data,
path: fileName,
directory: FilesystemDirectory.Data
}).then((result) => {
Filesystem.getUri({
directory: FilesystemDirectory.Data,
path: fileName
}).then((result) => {
console.log(result);
let path = result.uri.replace('file://', '_capacitor_');
this.image = this.sanitizer.bypassSecurityTrustResourceUrl(path);
}, (err) => {
console.log(err);
});
}, (err) => {
console.log(err);
});
}, (err) => {
console.log(err);
});
}, (err) => {
console.log(err);
}
);
}
In ionic 3 you have to use the cordova File plugin - please google. It is pretty straight forward to understand: you define the original directory where the file is, the original name of the file, the target directory, and a new name for the file inside that function. The principle is the same.
To download the File to the Download directory you need to use Cordova File Plugin:
import { File } from '#ionic-native/file/ngx';
constructor(
private file: File,
) { }
this.file.writeFile(this.file.externalRootDirectory + '/Download/', user_log.xlsx, blob, { replace: true })
.then(() => {
alert('File has been downloaded. Please check your downloads folder.')
enter code here
},
(err) => {
alert("Sorry. An error occurred downloading the file: " + err);
enter code here
});
})
It works in Ionic 4 as well.

Upload image to server with XMLHttpRequest and FormData in React-Native

I am trying to upload image to server with progress by using the example provided by:
https://gist.github.com/Tamal/9231005f0c62e1a3f23f60dc2f46ae35
I checked some tutorials, the code should works. But the uri in Android show uri
uri: content://media/external/images/media/4985
The URI come from the component
https://github.com/jeanpan/react-native-camera-roll-picker
The URI should be
file://....
So, why the upload code not working.
How can I convert the
content://... to file://.... to make it possible to upload image to server in React-native? or does my assumed is correct?
I am using react-native-image-picker to get image from library. I have written following code in one method name as selectPhoto() to select image from library.
selectedPhoto = () => {
//Open Image Picker
const options = {
quality: 1.0,
maxWidth: 500,
maxHeight: 500,
};
ImagePicker.showImagePicker(options, (response) => {
//console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled photo picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
}
else {
let source = {uri :response.uri};
console.log(source.uri);
this.setState({
profilePhoto: source
});
}
}); }
This will give me uri of selected image and I have set in state variable. then write following code to upload image.
var profiePicture = {
uri: this.state.profilePhoto.uri,
type: 'image/jpg', // or photo.type image/jpg
name: 'testPhotoName',
}
// API to upload image
fetch('http://www.example.com/api/uploadProfilePic/12345', {
method: 'post',
headers:{
'Accept': 'application/json',
'content-type': 'multipart/form-data',
},
body: JSON.stringify({
'profile_pic' : profiePicture
})
}).then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
})
.catch((error) => {
console.error(error);
});
This code is working in one of the my project.

Categories

Resources