Home > Net >  Expo Image Picker With Rails API gets Errno::ENOENT (No such file or directory @ rb_sysopen
Expo Image Picker With Rails API gets Errno::ENOENT (No such file or directory @ rb_sysopen

Time:06-19

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])

  • Related