I have this code, which can be run after device ready since it's on a secondary route. I'm working on Android at this time.
import { File } from "#ionic-native/file/ngx";
import { FileTransfer, FileTransferObject } from "#ionic-native/file-transfer/ngx";
constructor(private _transfer: FileTransfer,
private _platform: Platform,
private _file: File){
}
startDownload(file: XmatFile): void {
this.docsLoading = !0;
let path = void 0;
let visualPath = "";
if (this._platform.is("ios")) {
path = this._file.documentsDirectory;
visualPath = path;
}
else {
path = this._file.externalRootDirectory + "Download/";
visualPath = path.replace("file://", "");
}
this._checkPaths(path);
const fileTransfer: FileTransferObject = this._transfer.create();
fileTransfer.download(file.url, path + `tmp_${+new Date()}.pdf`, true, {
"content-type": mobSfcContentTypes.pdf
})
.finally(() => this.docsLoading = !1)
.then((downloadedFile) => {
(window as any).resolveLocalFileSystemURL(path, (dir) => {
dir.getFile(file.fileName, {create: true}, (newFile) => {
newFile.createWriter((fileWriter) => {
fileWriter.write(downloadedFile);
fileWriter.onwrite = () => {
this._snack(!0, `File scaricato in ${visualPath}`);
};
}, () => {
this._snack(!1, `Errore salvataggio in ${visualPath}`);
});
});
});
}, (error) => {
console.warn("mob-sfc-help => DOC download error", error);
this._sfcFunctionsSrv.showErrorAlert(`Non è stato possibile scaricare il file ${file.fileName}.
<br />Si prega di riprovare più tardi ed eventualmente aprire un ticket`);
});
}
I have a problem. The download goes ultra quick and saves a two files, but both are very small (a few bytes), while the target pdf is around 2MB.
Am I doing something wrong?
I solved it this way
import {HTTP} from "#ionic-native/http/ngx";
export class MyComponent {
constructor(private _nativeHttp: HTTP) {
}
doDownloadToDevice(file: MyFileModel):void {
this._spinner.show();
this._nativeHttp.downloadFile(file.url, {}, {}, this._downloadPath)
.finally(() => this._spinner.hide())
.then((_r_) => {
console.info("SUCCESS");
}, (e) => {
console.warn("Download error", e);
});
}
Hope this helps.
Related
I figured out it is not possible to share video content onto Instagram directly on Android in behalf of the user. This was my original intention.
Seems I can not use navigator.share call which works on iOS but not on Android, or only for text and url, but not for video / mp4.
I would not use MediaStore and similar React Nativ solutions as my app is a regular React.
What elso approach do you know?
I have now this:
const showShareDialog = async () => {
try {
log(
{
text: 'setIsDownloadFileInProgress(true) ' + getTempUserShortId(),
},
env
)
setIsDownloadFileInProgress(true)
const res = await axios.get(
`https://t44-post-cover.s3.eu-central-1.amazonaws.com/${imgId}.mp4`,
{ withCredentials: false, responseType: 'blob' }
)
setIsDownloadFileInProgress(false)
const shareData = {
files: [
new File([res.data], `${imgId}.mp4`, {
type: 'video/mp4',
}),
],
title: 'Megosztom',
text: 'Mentsd le a képekbe, és oszd meg storyban.',
}
//showShareDialog(shareData, 0)
if (navigator.share && !isDesktop) {
log(
{
text:
`navigator.share && !isDesktop shareData.files[0].size: ${shareData.files[0].size} ` +
getTempUserShortId(),
},
env
)
if (isAndroid()) {
const { status } = await MediaLibrary.requestPermissionsAsync()
if (status === 'granted') {
const asset = await MediaLibrary.createAssetAsync(res.data)
await MediaLibrary.createAlbumAsync(`${imgId}.mp4`, asset, false)
}
} else {
navigator
.share(shareData)
.then(() => {
log(
{
text: `'The share was successful 1 ` + getTempUserShortId(),
},
env
)
})
.catch((error) => {
log(
{
text:
`There was an error sharing 1 ${error} ` +
getTempUserShortId(),
},
env
)
})
}
} else {
log(
{
text: 'else ' + getTempUserShortId(),
},
env
)
setIsDesktopDownloadDialogVisible(true)
}
} catch (error) {
console.error(error)
log(
{
text: `a onclick error 2: ${error} ` + getTempUserShortId(),
},
env
)
}
}
I was using tipsi-stripe library but now i migrated it to #stripe/stripe-react-native library but i am unable to create token and get country name from card , please let me know how to implement it ,Thanks in advance.
------------------ Tipsi-stripe Code ----------------
import stripe, { PaymentCardTextField, } from 'tipsi-stripe'
stripe
.paymentRequestWithCardForm()
.then(stripeTokenInfo => {
this.state.loading = true
console.log('Token created', { stripeTokenInfo });
-------------- New Code without Create token ---------------------
import { CardField, useStripe ,confirmPayment, loading} from '#stripe/stripe-react-native';
export default class CheckoutSignin extends Component {
state = {
TotalAmount:null,
clientSecret:null
}
componentDidMount(){
console.log("Total Amount : " + this.props.route.params.TotalAmount);
this.state.TotalAmount = this.props.route.params.TotalAmount;
this.setState(this.state)
}
fetchPaymentIntentClientSecret = async () => {
makePayment(100,"AUD").then(r => {
if(r.Status === "Success"){
this.state.clientSecret = r.ClientSecret;
this.setState(this.state)
// alert("Payment Indent Success");
// console.log("1===> "+ clientSecret);
this.handlePayPress();
// console.log("3===> "+ clientSecret);
}
else {
alert("Payment Indent Failed.");
}
}).catch(e => {
alert(e)
})
};
handlePayPress = async () => {
const {paymentIntent, error} = await confirmPayment(this.state.clientSecret, {
paymentMethodType: 'Card',
paymentMethodData: {
// email: _userInfo.email,
},
});
if (error) {
console.log('Payment confirmation error', error);
Alert.alert("Error","Payment confirmation error", error);
} else if (paymentIntent) {
console.log('Success from promise', paymentIntent);
// Alert.alert("Success","Succeed Payment with 3ds");
this.props.navigation.navigate("Thankyou")
}
}
}
I’m downloading a file, and I’ve expected open the file after finished downloading, but this does not work, it’s viewed on a black screen when opening using Linking, and I open this file in the folder where it is and it opens correctly. How can I fix this?
This is the URL of the file in STORAGE:
content://com.android.externalstorage.documents/tree/primary%3ADownload%2FSigaa/document/primary%3ADownload%2FSigaa%2Fhistory.pdf
My code:
const downloadPath = FileSystem.documentDirectory! + (Platform.OS == "android" ? "" : "");
const ensureDirAsync: any = async (dir: any, intermediates = true) => {
const props = await FileSystem.getInfoAsync(dir);
if (props.exists && props.isDirectory) {
return props;
}
let _ = await FileSystem.makeDirectoryAsync(dir, { intermediates });
return await ensureDirAsync(dir, intermediates);
};
const downloadFile = async (fileUrl) => {
if (Platform.OS == "android") {
const dir = ensureDirAsync(downloadPath);
}
let fileName = "history";
const downloadResumable = FileSystem.createDownloadResumable(
fileUrl,
downloadPath + fileName,
{}
);
console.log(downloadPath);
try {
const { uri } = await downloadResumable.downloadAsync();
saveAndroidFile(uri, fileName);
} catch (e) {
console.error("download error:", e);
}
};
const saveAndroidFile = async (fileUri, fileName = "File") => {
try {
const fileString = await FileSystem.readAsStringAsync(fileUri, { encoding: FileSystem.EncodingType.Base64 });
if (local === "") {
const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync();
if (!permissions.granted) {
return;
}
await AsyncStorage.setItem("local", permissions.directoryUri);
}
try {
await StorageAccessFramework.createFileAsync(local, fileName, "application/pdf")
.then(async (uri) => {
await FileSystem.writeAsStringAsync(uri, fileString, { encoding: FileSystem.EncodingType.Base64 });
Linking.openURL(uri);
alert("Success!");
})
.catch((e) => {});
} catch (e) {
throw new Error(e);
}
} catch (err) {}
};
The black screen when opening:
I solved this by implementing the intent launcher api for android and the sharing api for ios.
To make it work it is important to provide the mimeType of the file (or UTI for IOS). You can extract it manually from the file extension but there's a library for that on RN: react-native-mime-types.
Actually I think any library that doesn't deppend on node core apis shoud work just fine.
Here's the code:
const openFile = async (fileUri: string, type: string) => {
try {
if (Platform.OS === 'android') {
await startActivityAsync('android.intent.action.VIEW', {
data: fileUri,
flags: 1,
type,
});
} else {
await shareAsync(fileUri, {
UTI: type,
mimeType: type,
});
}
} catch (error) {
// do something with error
}
};
I'm using the following code to download a file (can be a PDF or a DOC) and then opening it using Linking.
const { dirs } = RNFetchBlob.fs;
let config = {
fileCache : true,
appendExt : extension,
addAndroidDownloads : {
useDownloadManager : false,
notification : false,
title : 'File',
description : 'A file.',
path: `${dirs.DownloadDir}/file.${extension}`,
},
};
RNFetchBlob.config(config)
.fetch(
method,
remoteUrl,
APIHelpers.getDefaultHeaders()
)
.then((res) => {
let status = res.info().status;
if (status == 200) {
Linking.canOpenURL(res.path())
.then((supported) => {
if (!supported) {
alert('Can\'t handle url: ' + res.path());
} else {
Linking.openURL(res.path())
.catch((err) => alert('An error occurred while opening the file. ' + err));
}
})
.catch((err) => alert('The file cannot be opened. ' + err));
} else {
alert('File was not found.')
}
})
.catch((errorMessage, statusCode) => {
alert('There was some error while downloading the file. ' + errorMessage);
});
However, I'm getting the following error:
An error occurred while opening the file. Error: Unable to open URL:
file:///Users/abhishekpokhriyal/Library/Developer/CoreSimulator/Devices/3E2A9C16-0222-40A6-8C1C-EC174B6EE9E8/data/Containers/Data/Application/A37B9D69-583D-4DC8-94B2-0F4AF8272310/Documents/RNFetchBlob_tmp/RNFetchBlobTmp_o259xexg7axbwq3fh6f4.pdf
I need to implement the solution for both iOS and Android.
I think the easiest way to do so is by using react-native-file-viewer package.
It allows you to Prompt the user to choose an app to open the file with (if there are multiple installed apps that support the mimetype).
import FileViewer from 'react-native-file-viewer';
const path = // absolute-path-to-my-local-file.
FileViewer.open(path, { showOpenWithDialog: true })
.then(() => {
// success
})
.catch(error => {
// error
});
So, I finally did this by replacing Linking by the package react-native-file-viewer.
In my APIHelpers.js:
async getRemoteFile(filePath, extension, method = 'GET') {
const remoteUrl = `${API_BASE_URL}/${encodeURIComponent(filePath)}`;
const { dirs } = RNFetchBlob.fs;
let config = {
fileCache : true,
appendExt : extension,
addAndroidDownloads : {
useDownloadManager : false,
notification : false,
title : 'File',
description : 'A file.',
path: `${dirs.DownloadDir}/file.${extension}`,
},
};
return new Promise(async (next, error) => {
try {
let response = await RNFetchBlob.config(config)
.fetch(
method,
remoteUrl,
this.getDefaultHeaders()
);
next(response);
} catch (err) {
error(err);
}
});
}
In my Actions.js
export function openDocument(docPath, ext) {
return async (dispatch) => {
dispatch(fetchingFile());
APIHelpers.getRemoteFile(docPath, ext).then(async function(response) {
dispatch(successFetchingFile());
let status = response.info().status;
if (status == 200) {
const path = response.path();
setTimeout(() => {
FileViewer.open(path, {
showOpenWithDialog: true,
showAppsSuggestions: true,
})
.catch(error => {
dispatch(errorOpeningFile(error));
});
}, 100);
} else {
dispatch(invalidFile());
}
}).catch(function(err) {
dispatch(errorFetchingFile(err));
});
}
}
In my Screen.js
import { openDocument } from 'path/to/Actions';
render() {
return <Button
title={'View file'}
onPress={() => this.props.dispatchOpenDocument(doc.filepath, doc.extension)}
/>;
}
.
.
.
const mapDispatchToProps = {
dispatchOpenDocument: (docPath, ext) => openDocument(docPath, ext),
}
Are you downloading it from the web? I can see the pdf path is attached at the end of the error path.
For web URLs, the protocol ("http://", "https://") must be set accordingly!
Try to append appropriate schemes to your path. Check it out from the link mentioned below.
This can be done with 'rn-fetch-blob'
RNFetchBlob.android.actionViewIntent(fileLocation, mimeType);
I developed a mobile app to help sharing things. The user has to give infos about what he is sending and he can add a picture of the object. So i used the cordova file, camera and fileTransfert plugins. It worked fine on most of the devices i tested on, but i discovered that in some other phone, it doesn't. While doing some tests and research on one of those phones, i discovered that the upload() method of FileTransfert i use to send images to online server seems like not able to reach the folder where the image is stored. Here is a sample of my code. Would you please help me to confirm if i am rigth and how to make those phones to be able to post pictures on the platform?
public presentActionSheet(picture) {
if(this.translateService.currentLang=='fr'){
let actionSheet = this.actionSheetCtrl.create({
title: 'Quelle est la source?',
buttons: [
{
icon: 'images',
text: 'Mon téléphone',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY, picture);
}
},
{
icon: 'camera',
text: 'Ma Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA, picture);
}
},
{
text: 'Annuler',
role: 'cancel'
}
]
});
actionSheet.present();
}else{
let actionSheet = this.actionSheetCtrl.create({
title: 'What is the source?',
buttons: [
{
icon: 'images',
text: 'My Phone',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY, picture);
}
},
{
icon: 'camera',
text: 'My Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA, picture);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
actionSheet.present();
}
};
presentToast(message_error) {
let toast = this.toastCtrl.create({
message: message_error,
cssClass: 'alert-box',
position: 'middle',
showCloseButton: true,
closeButtonText: "OK"
});
toast.present();
}
//Here is the function to take a picture
public takePicture(sourceType, picture) {
// Create options for the Camera Dialog
var options = {
quality: 100,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
// Get the data of an image
this.camera.getPicture(options).then((imagePath) => {
// Special handling for Android library
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(), picture);
});
} else {
console.log('In the else condition');
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
this.copyFileToLocalDir(correctPath, currentName, this.createFileName(), picture);
}
}, (err) => {
if(this.translateService.currentLang=='fr'){
this.presentToast('Erreur, pas d\'image selectionnée.');
}else{
this.presentToast('Error, no image selected.');
}
});
}
// Create a new name for the image
private createFileName() {
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
return newFileName;
}
// Copy the image to a local folder
//cordova.file.dataDirectory
private copyFileToLocalDir(namePath, currentName, newFileName, picture) {
this.file.copyFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(success => {
if(picture == "imageOne"){
this.mainImage = newFileName;
}else if(picture == "imageTwo"){
this.secondImage = newFileName;
}else{
this.thirdImage = newFileName;
}
//this.lastImage = newFileName;
}, error => {
if(this.translateService.currentLang=='fr'){
this.presentToast('Erreur, le fichier n\'a pas pu etre sauvegardé.');
}else{
this.presentToast('Error, file could not be saved.');
}
console.log(error);
});
}
// Always get the accurate path to your apps folder
public pathForImage(img) {
if (img === null) {
return '';
} else {
return cordova.file.dataDirectory + img;
}
}
public uploadImage(picture) {
// Destination URL
var url = "http://donation.oneclub1.org/donation-new/web/api/upload/image?context=donations";
// File for Upload
var targetPath: any;
if(picture == "imageOne"){
targetPath = this.pathForImage(this.mainImage);
}else if(picture == "imageTwo"){
targetPath = this.pathForImage(this.secondImage);
}else{
targetPath = this.pathForImage(this.thirdImage);
}
// File name only
var filename: any;
if(picture == "imageOne"){
filename = this.mainImage;
}else if(picture == "imageTwo"){
filename = this.secondImage;
}else{
filename = this.thirdImage;
}
var options = {
fileKey: "file",
fileName: filename,
chunkedMode: false,
mimeType: "multipart/form-data",
params : {'fileName': filename}
};
const fileTransfer: TransferObject = this.transfer.create();
// Use the FileTransfer to upload the image
return fileTransfer.upload(targetPath, url, options);/*.then(data => {
if(picture == "imageOne"){
this.mainImageLocal = parseInt(data.response);
}else if(picture == "imageTwo"){
this.secondImageLocal = parseInt(data.response);
}else{
this.thirdImageLocal = parseInt(data.response);
}
//this.presentToast('this is your image id'+this.mainImageLocal);
}, err => {
this.loading.dismissAll();
this.presentToast('Error while uploading file.');
})*/;
}
publish(){
if(this.mainImage!=null){
this.loading = this.loadingCtrl.create({
content: this.content2,
});
this.loading.present();
//var categoryId: number;
for(let parent of this.categories){
if(parent.name == this.asking_form_group.value.subcategory){
this.categoryId=parent.id;
console.log('Id found and it is:'+this.categoryId);
break;
};
};
//var userId: number;
if(localStorage.getItem('userId')){
this.userId= parseInt(localStorage.getItem('userId'));
console.log('got the user id in nmber:'+this.userId);
};
var headers = new Headers();
headers.append("Accept", 'application/json');
headers.append('Content-Type', 'application/json' );
let options = new RequestOptions({ headers: headers });
this.uploadImage('imageOne').then(data => {
this.mainImageLocal = parseInt(data.response);
this.postParams = {
name: this.asking_form_group.value.name,
category: this.categoryId,
description: this.asking_form_group.value.description,
image: this.mainImageLocal,
user: this.userId
}
this.http.post(this.Api+"/donations/requests?api_key="+localStorage.getItem('userApiKey'), this.postParams, options).map(res => res.json())
.subscribe(data => {
this.loading.dismissAll();
if(this.translateService.currentLang=='fr'){
this.presentToast('Félicitations!!Votre demande a été postée sur la plateforme!')
}else{
this.presentToast ('Congratulations !! Your request has been posted on the platform!')
}
this.events.publish('ask:posted', 1);
this.navCtrl.setRoot(Dashboard);
}, error => {
console.log(error);
//this.asking_form_group.reset();
this.testor = error.response;
this.loading.dismissAll();
this.presentToast(this.error);
});
});
}else{
this.loading = this.loadingCtrl.create({
content: this.content2,
});
this.loading.present();
//var categoryId: number;
for(let parent of this.categories){
if(parent.name == this.asking_form_group.value.subcategory){
this.categoryId=parent.id;
console.log('Id found and it is:'+this.categoryId);
break;
};
};
if(localStorage.getItem('userId')){
this.userId= parseInt(localStorage.getItem('userId'));
console.log('got the user id in nmber:'+this.userId);
};
var headers = new Headers();
headers.append("Accept", 'application/json');
headers.append('Content-Type', 'application/json' );
let options = new RequestOptions({ headers: headers });
this.postParams = {
name: this.asking_form_group.value.name,
category: this.categoryId,
description: this.asking_form_group.value.description,
image: this.mainImageLocal,
user: this.userId
}
this.http.post(this.Api+"/donations/requests?api_key="+localStorage.getItem('userApiKey'), this.postParams, options).map(res => res.json())
.subscribe(data => {
this.loading.dismissAll();
if(this.translateService.currentLang=='fr'){
this.presentToast('Félicitations!!Votre demande a été postée sur la plateforme!')
}else{
this.presentToast ('Congratulations !! Your request has been posted on the platform!')
}
this.events.publish('ask:posted', 1);
this.navCtrl.setRoot(Dashboard);
}, error => {
console.log(error);
//this.asking_form_group.reset();
this.testor = error.response;
this.loading.dismissAll();
this.presentToast(this.error);
});
};
}
Sorry i found what the issue was and i fogot to put it here. The problem was actually about filesize. Filetransfert default limit is 7.5Mo. Sending file greater than that would fail. In some phones, camera default configurations put the picture size to 8 or greater Mpx. So that why it could not work in those phones.