I'm creating a mobile app in React Native using Expo. I want to catch picture from the mobile I'm doing in my CameraScreen.js
async function handlePictureTaken() {
console.log('Picture taken')
try {
const photo = await cameraRef.current.takePictureAsync({base64: true});
await cameraRef.current.pausePreview();
navigation.navigate('ConfirmPhoto', {photo: photo});
}
catch (error) {
console.log(error)
}
}
Once I have it I therefore go to my ConfirmCameraScreen.js but there I don't do anything with my photo and send it directly to my ConfirmAnimalScreen.js
import { useState, useEffect } from 'react';
import { Text, View, Image } from 'react-native';
import { detectAnimal } from '../../util/animalIdentification';
function ConfirmAnimalScreen({ route }) {
const [animal, setAnimal] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
detectAnimal(route.params.photo.uri)
.then(data => {
setAnimal(data);
})
.catch(err => {
console.error(err);
setError(err);
});
}, [route.params.photo.uri]);
if (error) {
return <Text>Error: {error.message}</Text>;
}
if (!animal) {
return <Text>Loading...</Text>;
}
return (
<View>
<Text>ConfirmAnimalScreen</Text>
</View>
);
}
export default ConfirmAnimalScreen;
Here I just call the function detectAnimal() with the uri of my photo stored locally.
import { INATURALIST_API_KEY, INATURALIST_API_URL } from '@env'
export async function detectAnimal(photo) {
console.log(photo)
try {
const response = await fetch(photo);
const blob = await response.blob();
const formData = new FormData();
formData.append('image', blob);
console.log('formData', formData);
const url = `${INATURALIST_API_URL}computervision/score_image`;
try {
const animalResponse = await fetch(url, {
method: 'POST',
headers: {
'Authorization': INATURALIST_API_KEY,
'Accept': 'application/json',
},
body: formData,
});
console.log(`${animalResponse.status} ${animalResponse.statusText}`);
return animalResponse.data;
} catch (error) {
console.error('Error:', error.message);
}
} catch (error) {
console.error('Error:', error.message);
}
}
Here I'm trying to call the Inaturalist API (https://api.inaturalist.org/v2/docs/)
However, it always return an Network request failed.
According to me (but not sure), it is because the image is not a valid blob, but I've tried a lot of differents stuffs and it never works while from Postaman it is working well.
EDIT:
I change a bit my code and instead of transforming my image into a blob I directly send the image.uri
export async function detectAnimal(photo) {
console.log(photo)
try {
const formData = new FormData();
formData.append('image', photo);
console.log('formData', formData);
const url = `${INATURALIST_API_URL}computervision/score_image`;
try {
const animalResponse = await fetch(url, {
method: 'POST',
headers: {
'Authorization': INATURALIST_API_KEY,
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData,
});
console.log('animalResponse', animalResponse);
return animalResponse.data;
} catch (error) {
console.error('Error:', error.errors[0].message);
console.error('Error:', error.status);
}
} catch (error) {
console.error('Error:', error.message);
}
}
I now have an error 422
END OF EDIT
I've tried several things:
- I made the request with axios, however, it puts the Content-Type to x-www-form-encoded while the API is waiting for multipart/form-data. It just gave me more context on the error, it is an request error and config error ("_response": "Unrecognized FormData part.")
- I tried to use the base64 format of the image to transform it into a blob... Same problem
- I tried to reduce the size of the image... same problem -I tried with a new API-key... same
On Postman and Inaturalist API everything work well with the same API_key