Display profile picture with expo - react-native

I am new to React native and expo and I'm trying to handle the user's profile (edit the profile, profile picture, etc...).
I managed to successfully retrieve the user's info from the API and send the changes like the username or password to it but I can't do it for the profile picture.
I've already tried with axios (what I use to communicate to the API):
async componentDidMount() {
const token = await this.getToken();
const AuthStr = 'Bearer '.concat(token);
await axios.get('https://....jpg', { headers: { Authorization: AuthStr } })
.then(res => {
console.log('RESPONSE: ', res.data);
})
.catch((error) => {
console.log('error ' + error);
});
}
But it returns me error 500
Then I tried with the FileSystem from Expo:
let download = FileSystem.createDownloadResumable('https://...jpg',
FileSystem.documentDirectory + 'profile.jpg',
{ headers: { Authorization: AuthStr } },
null,
null);
try {
const { uri } = await download.downloadAsync();
console.log('Finished downloading to ', uri);
this.setState({
pic: uri,
});
} catch (e) {
console.error(e);
}
let info = await FileSystem.getInfoAsync(this.state.pic, null);
console.log(info);
The log says the file is downloaded and the path is something like this:
file:///var/mobile/Containers/Data/Application/20CF6F63-E14D-4C14-9078-EEAF50A37DE1/Documents/ExponentExperienceData/%2540anonymous%app/profile.jpg
The getInfoAsync() returns true, meanings that the image exists in the filesystem. When I try to render it with
<Image source={{uri: this.state.pic}}/>
It displays nothing. What do I do wrong ?

the temporary solution is to move the image to the gallery
let { uri } = await FileSystem.downloadAsync(this.props.item.imgUrl, FileSystem.cacheDirectory + ${this.props.item}.jpg);
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (status === 'granted') {
CameraRoll.saveToCameraRoll(uri).then((uriGallery) => {
//here you have the url of the gallery to be able to use it
});
}
This is the link I referred to in writing the answer.

Related

React Native Facebook User Photos is Denied

I have a react native app and i can login with facebook. However I can't get the users photo. First of all FB hash key is correct and my app is in live mode. I sent the app to APP REVIEW and the photos are always denied by team and they are telling me they can't get the photos of the users. I use "react-native-fbsdk-next": "^4.3.0" and we use our own api url for photos, not using Graph Api of FB. There is [user_photos] as well beside public_profile. Does anyone know the reason for this ? After I login to Facebook, i try to upload photo via FB and it displays a pop up saying " facebook photos permission is denied. This permission allows your app to read photos of Facebook". Why facebook team denies user photo access ? what else should do to make it work ? My login code implementation is below. I could not find anything on Google regarding this kind of issue. Please help
export const facebookLogin = snackBarBottomMargin => {
return async dispatch => {
try {
const result = await LoginManager.logInWithPermissions([
'public_profile',
'user_photos',
]);
if (!result.isCancelled) {
const data = await AccessToken.getCurrentAccessToken();
if (data && data.accessToken) {
await storage.storeData(
PREFERENCES.FB_ACCESS_TOKEN,
JSON.stringify(data),
);
return data;
} else {
console.log('Facebook result fetch token error cancelled');
return false;
}
} else {
console.log('Login cancelled');
return false;
}
} catch (error) {
dispatch(
showSnackbar(strings.login.facebookLoginError, snackBarBottomMargin),
);
return false;
}
};
};
export function handleFetchFBPhotos(accessToken, after) {
return async dispatch => {
function onSuccess(success) {
dispatch(fetchMediaSuccess(success));
console.log('success', success);
return success;
}
function onError(error) {
dispatch(fetchMediaFailed(error));
console.log('error', error);
return error;
}
try {
dispatch(fetchMediaRequest(true));
const config = {
baseURL: Config.FACEBOOK_BASE_URL,
params: {
type: 'uploaded',
fields: 'images',
after,
},
headers: {Authorization: `Bearer ${accessToken}`},
};
const response = await axios.get(FACEBOOK_PHOTOS, config);
if (response.data && response.data.data) {
console.log('response.data', response.data);
console.log('response.data.data', response.data.data);
console.log('onSuccess(response.data)', onSuccess(response.data));
return onSuccess(response.data);
}
} catch (error) {
const errorObj = getErrorResponse(
error,
Config.FACEBOOK_BASE_URL + FACEBOOK_PHOTOS,
);
console.log('onError(errorObj.message)', onError(errorObj.message));
return onError(errorObj.message);
}
};
}

How to save pdf from an api response to file system in react native?

I'm receieving a blob from api and i want to save it as a pdf document to file system.But on saving I'm getting a file with size 0B in my mobile
Code
export const getParkingReciept = (bookindId) => {
return async function (dispatch, getState) {
try {
const TOKEN = getState().Auth.token;
const formdata = new FormData();
formdata.append("booking_id", bookindId);
RNFetchBlob.fetch(
'POST',
`${BASE_URL}parking-space/booking/receipt`,
{
'Accept': 'application/json',
'Authorization': `Bearer ${TOKEN}`,
'Content-Type': 'multipart/form-data'
},[
{ name : 'booking_id', data: bookindId.toString()}
]
)
.then(
response => {
console.log("response is ",response);
response.blob().then(res=>console.log(checkPermission(res,response.taskId)));
console.log("pdf base64 is ", response.base64());
}
).catch((error) => {
// error handling
console.log("Error", error)
}
);
}catch (e) {
if (e.response) {
console.log("error response is ", e.response);
} else if (e.request) {
console.log(e.request);
} else {
console.log('Error', e);
}
console.log(e.config);
}
}
const checkPermission=async (file,name) => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
{
title: "Cool Photo App Camera Permission",
message:
"Cool Photo App needs access to your camera " +
"so you can take awesome pictures.",
buttonNeutral: "Ask Me Later",
buttonNegative: "Cancel",
buttonPositive: "OK"
}
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can write to external storage");
var path = RNFS.DownloadDirectoryPath + '/'+name+".pdf";
console.log("pdf being written is ",file);
RNFS.writeFile(path, file, 'utf8')
.then((success) => {
console.log('FILE WRITTEN!');
RNFetchBlob.fs.scanFile([ { path : path, mime : "application/pdf" } ])
// .then(() => {
// console.log("scan file success")
// })
// .catch((err) => {
// console.log("scan file error")
// })
})
.catch((err) => {
console.log(err.message);
});
} else {
console.log("permission denied");
}
} catch (err) {
console.warn(err);
}
};
reponse I get from fetch is
on calling blob() function of response what I get is
There is type Application/pdf there ,but in base 64 string does not start with JVBERi it starts with some SFRUU,Is that a valid pdf file?. What am I missing ? what am I doing wrong here?
This answer solves your problem , gives you detailed explanation about how to download files from a network request using rn fetch blob
https://stackoverflow.com/a/56890611/7324484
Once you downloaded the file or you can open the pdf directly using
https://www.npmjs.com/package/react-native-pdf

How to upload image with express-fileupload from CKEditor5 properly?

My api as follows
router.post("/upload", async (req, res) => {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send("No files were uploaded.");
}
console.log(req.files)
let file = req.files.upload;
let uploadPath = __dirname + "/../public/" + file.name;
file.mv(uploadPath, function (err) {
if (err) {
console.log(err)
return res.status(500).send(err)
}
res.sendStatus(200);
});
});
My react component
<CKEditor
editor={ClassicEditor}
config={{
ckfinder: {
uploadUrl: "/api/upload",
},
}}
data={props.state.tech.assess_info}
onChange={(event, editor) => {
..
}}
/>
Currently when I upload image from CKeditor, image is successfully uploaded(written to "public/{filename}" on server side). However CKEditor error popups and stating "cannot upload". I believe CKeditor is expecting specific response code, not just HTTP status 200. What do you guys think?
Ckeditor is expecting following response from API.
res.status(200).json({
uploaded: true,
url: `/uploads/${file.name}`,
});
Whole api code if anyone needs.
// Upload a file
router.post("/upload", async (req, res) => {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send("No files were uploaded.");
}
let file = req.files.upload;
let uploadPath = __dirname + "/../public/uploads/" + file.name;
file.mv(uploadPath, function (err) {
if (err) return res.status(500).send(err);
res.status(200).json({
uploaded: true,
url: `/uploads/${file.name}`,
});
});
});

IBM IAM IamAuthenticator getToken is not a function

I'm trying to get a token to use IBM Watson Speech-to-Text in my app. Here's my code:
const { IamAuthenticator } = require('ibm-cloud-sdk-core');
const authenticator = new IamAuthenticator({
apikey: 'myApiKey',
});
authenticator.getToken(function (err, token) {
if (!token) {
console.log('error: ', err);
} else {
// use token
}
});
The error message is authenticator.getToken is not a function.
The documentation says:
string IBM.Cloud.SDK.Core.Authentication.Iam.IamAuthenticator.GetToken ( )
I've tried both getToken and GetToken. Same error message. The code isn't complicated, what am I doing wrong?
This is what worked for me with the latest ibm-watson node-sdk,
Install node-sdk with this command
npm install --save ibm-watson
Then, use this code snippet in your app.js or server.js node file to receive the IAM access token
const watson = require('ibm-watson/sdk');
const { IamAuthenticator } = require('ibm-watson/auth');
// to get an IAM Access Token
const authorization = new watson.AuthorizationV1({
authenticator: new IamAuthenticator({ apikey: '<apikey>' }),
url: ''
});
authorization.getToken(function (err, token) {
if (!token) {
console.log('error: ', err);
} else {
console.log('token: ', token);
}
});
You can also directly use the IamAuthenticator with Speech to Text
const fs = require('fs');
const SpeechToTextV1 = require('ibm-watson/speech-to-text/v1');
const { IamAuthenticator } = require('ibm-watson/auth');
const speechToText = new SpeechToTextV1({
authenticator: new IamAuthenticator({ apikey: '<apikey>' }),
url: 'https://stream.watsonplatform.net/speech-to-text/api/'
});
const params = {
// From file
audio: fs.createReadStream('./resources/speech.wav'),
contentType: 'audio/l16; rate=44100'
};
speechToText.recognize(params)
.then(response => {
console.log(JSON.stringify(response.result, null, 2));
})
.catch(err => {
console.log(err);
});
// or streaming
fs.createReadStream('./resources/speech.wav')
.pipe(speechToText.recognizeUsingWebSocket({ contentType: 'audio/l16; rate=44100' }))
.pipe(fs.createWriteStream('./transcription.txt'));
See my answer in your other post that might help. You use BearerTokenAuthenticator if you want to manage the token authentication process yourself.

React native asyncstorage cannot get data

I'm starting my react-native project with npm start. On my emulator I have installed expo to view my application. Also I'm using http://ip:19001/debugger-ui/ to debug my application in google chrome.
I don't know what I'm doing wrong but I can't get any data from asyncstorage. Can you please give me some tips how to correct this problem.
In one of my activities I store data with;
storeDataInAsync1(idSchool,year) {
try {
//await AsyncStorage.removeItem('user');
AsyncStorage.setItem('dateRange', this.props.range);
AsyncStorage.setItem('idSchool', idSchool);
AsyncStorage.setItem('school_year', year);
} catch (error) {
// Error saving data
}
}
My call to this method;
async saveMyProfil() {
var formData = new FormData();
formData.append('id_school',this.props.idSchool);
formData.append('school_year', this.props.year);
await fetch(`${api.url}/my_profile/`, {
method: 'POST',
headers: {
"Content-Type": "multipart/form-data"
},
body: formData,
}).then((response) => response.json())
.then((json) => {
console.log('Response: ' + JSON.stringify(json));
this.storeDataInAsync1(json.id_school,json.school_year);
//_storeData(json.id_school,json.school_year);
//this.doStuff(json.id_school,json.school_year);
})
.catch((error) => {
});
}
back() {
//this.storeDataInAsync();
this.saveMyProfil();
this.props.navigation.goBack();
}
In another activity there is method to retrive data;
_retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('idSchool');
const year = await AsyncStorage.getItem('school_year');
if (value !== null && year !== null) {
// We have data!!
console.log('Id School: ' + value);
console.log('Year: ' + year);
}
} catch (error) {
// Error retrieving data
}
}
I call _retrieveData in;
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
this._retrieveData();
}