developers, I am using react-native-image-picker to upload images to the Nodejs server and MongoDB, when I select an image on react native app it is showing image fileName="null" on the console log. I am struggling for 3 weeks and couldn't find any solution. Below I have posted the console.log result:
Response = {"fileName": null, "fileSize": 13712705, "height": 3024, "isVertical": false, "origURL": "assets-library://asset/asset.HEIC?id=CC95F08C-88C3-4012-9D6D-64A413D254B3&ext=HEIC", "type": "image/jpeg", "uri": "file:///Users/shinobi/Library/Developer/CoreSimulator/Devices/9DBEA6D8-101E-4B9C-9DB0-D1CABA724AAF/data/Containers/Data/Application/44C0E455-2A43-40A3-A2EE-213A39B7743C/tmp/35A90028-55FA-4218-8FB7-34EB1DE62F58.jpg", "width": 4032}
Below is my react-native-image-picker code:
const ChangeTasbir = ({navigation, route}, props) => {
const [image, setImage] = useState(null);
const [id, setId] = useState(getDetails('id'));
const [isuploading, setIsuploading] = useState(false);
const selectImage = () => {
const options = {
noData: true,
};
ImagePicker.showImagePicker(options, response => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const source = {
uri: response.uri,
fileName: response.fileName,
data: response.data,
};
// You can also display the image using data:
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
setImage(source);
}
});
};
I'm using this options in my React native application on Android and works ok.
const options = {
mediaTypes: 'Images',
quality: 0.1,
};
ImagePicker.launchImageLibrary(options, (response) => {
if (response.didCancel !== true) {
this.setState({ profilePic: response, errorPic: false });
}
});
try this:
let path = response.uri;
if (Platform.OS === "ios") {
path = "~" + path.substring(path.indexOf("/Documents"));
}
if (!response.fileName) response.fileName = path.split("/").pop();
Related
I want to upload image in react native, so I use react native image picker. In my postman the api can upload image, but in mycode nothing update. in below example consume api in postman
in my code like this:
const handlePickImage = () => {
launchImageLibrary(
{
mediaType: 'photo',
quality: 0.5,
},
(response) => {
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const { uri, type, fileName } = response?.assets?.[0];
console.log(response?.assets);
if (uri) {
setSelectedImage({
name: formik.values.companyName.replace(/\s/g, '-'),
uri,
type,
fileName,
});
setPreviewImage(uri);
} else {
console.log('Fail to pick image!');
}
}
},
);
};
This is my logic for submit data
const formData = new FormData();
formData.append('image', selectedImage?.fileName);
await handleSubmit(formData);
const handleSubmit = async (input) => {
try {
const result = await axios.patch(`${BASE_URL}/company/profile`, input, {
headers: { Authorization: `Gosnix ${DataLoginReducers?.token}` },
});
if (result.status == 200 || result.status === 'success' || result.status == 201) {
formik.resetForm();
setModalActive({ status: false });
setErrorMessage('');
navigation.goBack();
}
} catch (error) {
console.log(error);
setModalActive({ status: true, type: 'error' });
setErrorMessage(translations['please.try.again']);
}
};
anyone help me?
in your headers add "Content-Type": "multipart/form-data". When sending formdata, you need to tell the backend what type of data to expect so in this case it would be multipart/form-data.
I have a component with function:
const selectImage = () => {
const options = {
maxWidth: 2000,
maxHeight: 2000,
storageOptions: {
skipBackup: true,
path: 'images'
}
};
launchImageLibrary(options, response => {
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const source = { uri: response.uri };
console.log(source);
setImage(source);
}
});
};
const uploadImage = async () => {
const { uri } = image;
console.log('uri check:', uri) //stands for the image location
const filename = uri.substring(uri.lastIndexOf('/') + 1);
setUploading(true);
setTransferred(0);
const task = storage()
.ref(filename)
.putFile(uri);
// set progress state
task.on('state_changed', snapshot => {
setTransferred(
Math.round(snapshot.bytesTransferred / snapshot.totalBytes) * 10000
);
});
try {
await task;
} catch (e) {
console.error(e);
}
setUploading(false);
Alert.alert(
'Photo uploaded!',
'Your photo has been uploaded to Firebase Cloud Storage!'
);
setImage(null);
};
that was to pick an image and upload to firebase, so i get the imageUri.
I want to add that image-uri into firestore, just need to get the correct ref instead of put all the code in one place.
on the other screen I just call <UploadImage/>.
can anyone guide me or give some information?
im trying to upload an image to AWS Presigned url. I can get presigned url then i can upload an image from Postman, but i try to send from React Native application, just uri info is sent (content://media/external/images/media/108721). I tried a lot of thing but i cant do it. Could you help me please?
I am using react-native-image-picker to select an image.
showImagePicker = () => {
const options = {
title: 'Profile Picture',
storageOptions: {
skipBackup: true,
path: 'images',
base64: true,
},
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const source = { uri: response.uri };
const avatarData = response;
let presignedUrl = "mypresignedurl";
const xhr = new XMLHttpRequest()
xhr.open('PUT', presignedUrl)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log('Image successfully uploaded to S3')
} else {
console.log('Error while sending the image to S3', xhr.responseText)
}
}
}
xhr.setRequestHeader('Content-Type', response.type)
xhr.setRequestHeader('content-lenght', response.fileSize)
xhr.send(response.uri);
this.setState({
avatarSource: source,
avatarData: avatarData,
imageModalVisibilty: true
});
}
});
}
I saw many example like this but i just only send uri string.
I solved this issue with another way. I had to get blob data :)
export const getBlob = async (fileUri) => {
const resp = await fetch(fileUri);
const imageBody = await resp.blob();
return imageBody;
};
export const uploadImageNew = async (uploadUrl, data) => {
const imageBody = await getBlob(data);
return fetch(uploadUrl, {
method: "PUT",
body: imageBody,
});
};
reference
I trying to upload a file image to API in postman thats work fine but when a i try file image from ImagePicker didnot work.
I think doing something wrong when create formdata
Handler
ImagePicker.showImagePicker(optionsImagePicker, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
// const source = { image: response.data };
let photo = { uri: response.uri}
let formdata = new FormData();
formdata.append("product[name]", 'test')
formdata.append("product[price]", 10)
formdata.append("product[category_ids][]", 2)
formdata.append("product[description]", '12dsadadsa')
formdata.append("product[images_attributes[0][file]]", {uri: photo.uri, name: 'image.jpg', type: 'image/jpeg'})
updateProfilePic(formdata)
// You can also display the image using data:
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
// this.setState({
// avatarSource: source,
// });
}
});
Service
export function uploadImageProfile(data: any): Promise<any> {
const config = {
headers: {
'Content-Type': 'multipart/form-data',
},
};
return api.post('/users/profilepic', {image: data}, config).then((res) => {
console.log(res.data);
return res.data;
});
}
Your form data must be like that.
formdata.append('file',{
uri: Platform.OS === 'android' ? photo.uri : 'file://' + photo.uri,
name: 'test',
type: 'image/jpeg' // or your mime type what you want
});
Then
axios.post('/users/profilepic', formdata, config).then((res) => {
console.log(res.data);
return res.data;
});
let formdata = new FormData();
formdata.append('file',{
uri: Platform.OS === 'android' ? photo.uri : 'file://' + photo.uri,
name: 'test',
type: 'image/jpeg'
});
use method:"POST" and spread formdata.getHeaders() into header
let reqObj = {
method: "POST",
url: 'http://example.com/upload/image',
headers: {
'x-sh-auth': token,
...formdata.getHeaders()
},
maxContentLength: Infinity,
maxBodyLength: Infinity
};
axios(reqObj).then(result => {
console.log(result)
}).catch(error => {
console.log(error)
});
I changed how I send image to the server. Now send im base64 and in server convert to file with fs.
const uploadImage = {
imageBase64: 'data:' + response.type + ';base64,' + response.data,
};
updateProfilePic(uploadImage);
server side
async saveImageProfile(imageBase64, logedUserData) {
let base64Image = imageBase64.imageBase64.split(';base64,').pop();
let type = imageBase64.imageBase64.split('image/').pop().split(';')[0];
let newFileName = `${logedUserData.id}.${type}`;
if (imageFileFilter(type)) {
const file = await fs.writeFile('./files/' + newFileName, base64Image, { encoding: 'base64' }, function (err) {
console.log('File created');
});
const url = `${baseUrl}/users/files/${newFileName}`;
this.updateRefProfilePic(url, logedUserData);
}
else {
throw new BadRequestException("Tipo de arquivo não suportado");
}
}
I am trying to make a resuable fuction with the react-native imagepicker library but when i import the function i get undefined from the component i imported it to. With a console.log i see its actually working. it is just not showing the image uploaded.
I tried returning the source and the actually function but it doesnt work
helperfunction.js
import ImagePicker from 'react-native-image-picker';
export const photoUpload =()=>{
const options = {
title: 'Select Avatar',
camera: [{ name: 'fb', title: 'Take a picture' }],
storageOptions: {
skipBackup: true,
path: 'images',
},
};
const action = ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.camera) {
console.log('User tapped custom button: ', response.camera);
} else {
const source = { uri: response.uri };
console.log(source)
return source;
}
})
return action;
}
App.js
import {photoUpload} from '../../../utilities/helper/photoUpload'
handlePhotoUpload = async () =>{
const data = await photoUpload()
console.log(data) (this comes back undefined)
if (data){
this.setState({
photo: data
});
}
}
If you have a look at the signature of the showImagePicker function from the docs, you'll see it has no return value:
static showImagePicker(options?, callback)
The reason you are still seeing results from the console log is that when you invoke the showImagePicker function it is calling your callback function asynchronously. To fix this issue, you can employ a promise like this:
export const photoUpload = () => {
const options = {
title: 'Select Avatar',
camera: [{name: 'fb', title: 'Take a picture'}],
storageOptions: {
skipBackup: true,
path: 'images',
},
};
return new Promise(((resolve, reject) => {
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
reject('User cancelled image picker');
} else if (response.error) {
reject('ImagePicker Error: ', response.error);
} else if (response.camera) {
reject('User tapped custom button: ', response.camera);
} else {
const source = {uri: response.uri};
resolve(source);
}
})
}))
}
You can leave your app.js the same as you are already waiting for the promise to resolve with 'await' meaning the data variable will result in the source result object from the promise