When I try to upload image via Expo's: ImagePicker I get:
Completed 500 Internal Server Error in 1ms (ActiveRecord: 2.8ms | Allocations: 637)
Errno::ENOENT (No such file or directory @ rb_sysopen - file:///data/user/0/host.exp.exponent/cache/ExperienceData/%40zilasino%2Frestaurant-management/ImagePicker/5f29f45c-4467-4360-bcc8-2651146837b3.jpg):
It does work fine when I hit the endpoint via Insomnia, the image is uploaded, but it doesn't work doing so via expo app running on Android Emulator. It seems like, the data is passing to rails, but for some reason rails is unable to find that file... Any ideas?
CreateMenuItem.js
const addMenuItem = async () => {
const menuItem = {
name,
price,
image: selectedImage.uri,
is_drink: isDrink ? true : false,
notes,
};
const resp = await createAccessory("menu_items", menuItem);
if(resp.type == 'success'){
fetchMenuItemData();
clearFields()
}
showMessage({
message: `${resp.msg}`,
position: "center",
duration: 2500,
style: { backgroundColor: resp.type == 'success' ? colors.PRIMARY : colors.ERROR },
titleStyle: { fontSize: 20 },
});
};
const createAccessory = async (accessory, payload) => {
return await axios.post(baseUrl '/' accessory, payload, {headers})
.then(resp => {
if (resp.data){
return { msg: i18n.t('saved'), type: 'success' }
} })
.catch(error => {
if (error.response) {
return { msg: error.response.data.name }
}
}
)
}
ImageUpload.js
const ImageUpload = ({ parentCallback, selectedImage }) => {
let openImagePickerAsync = async () => {
let permissionResult =
await ImagePicker.requestMediaLibraryPermissionsAsync();
if (permissionResult.granted === false) {
alert("Permission to access camera roll is required!");
return;
}
let pickerResult = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 1
});
if (pickerResult.cancelled === true) {
return;
}
parentCallback(pickerResult);
};
if (selectedImage != null) {
return (
<>
<Image
source={{ uri: selectedImage.uri }}
style={styles.thumbnail}
resizeMode="contain"
/>
<Button
title="X"
color={colors.PRIMARY}
onPress={() => parentCallback(null)}
/>
</>
);
} else {
return (
<>
<TouchableOpacity onPress={openImagePickerAsync} style={styles.button}>
<Text style={styles.buttonText}>{i18n.t("pickAnImage")}</Text>
</TouchableOpacity>
</>
);
}
};
controller.rb
class MenuItemsController < ApplicationController
...
def create
image = Cloudinary::Uploader.upload(params[:image])
menu_item = MenuItem.new(
image: image['url'],
)
end
...
end
CodePudding user response:
One possible issue could be that the path to the image file is incorrect. Try double-checking the path and make sure that the image file is in the correct location.
CodePudding user response:
I figured it out, I had to pass the image to Rails as a Base64 and not just its URI.
I've just added base64: true
option:
let pickerResult = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 1,
base64: true
})
and change one line in rails controller like so:
image = Cloudinary::Uploader.upload('data:image/jpeg;base64,' menu_item_params[:image])