wkh237 / react-native-fetch-blob

A project committed to making file access and data transfer easier, efficient for React Native developers.
MIT License
2.61k stars 1.57k forks source link

[request] Add to Expo? #299

Open allpwrfulroot opened 7 years ago

allpwrfulroot commented 7 years ago

Would it be possible to add this awesome package to the React Native project Expo? Unfortunately it's incompatible with packages that require react-native link.

nukes88 commented 7 years ago

im getting on my iOS device with the expo client: undefined is not an object (evaluating 'RNFetchBlob.DocumentDir')

just by putting the import line at the top

This is the same problem right?

wkh237 commented 7 years ago

This module must be linked. Otherwise, it will not work since many of APIs has a native implementation.

aaronbwatkins commented 7 years ago

This package is amazing. I'm using now expo too (which i love). I was using react-native-fetch-blob pre-expo and i LOVED it. Definitely a lifesaver. Now that I've built my app in Expo, I'm stuck again on getting images to Firebase. Is there a workaround to be able to use this package? Any recommendations would be amazing. Thanks so much!

allpwrfulroot commented 7 years ago

I've found a workaround with FormData (and scaphold.io not firebase):

async uploadImageAsync(uri, userId) {
    let formData = new FormData();
    formData.append("query", `
      mutation CreateFile($input: CreateFileInput!) {
        createFile(input: $input) {
          changedFile {
            id
            name
            blobMimeType
            blobUrl
            user {
              id
              username
            }
          }
        }
      }
    `)
    formData.append("variables", JSON.stringify({
      "input": {
        "name": "Profile Picture",
        "userId": `${userId}`,
        "blobFieldName": "photo"
      }
    }))
    formData.append('photo', {
      uri,
      name: `photo.jpg`,
      type: `image/jpg`
    })

    let options = {
      method: 'POST',
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      body: formData
    }
    return fetch(`https://${config.scapholdUrl}`, options)
  }
aaronbwatkins commented 7 years ago

thanks a lot @allpwrfulroot - really appreciate the assist.

lalatgithub commented 7 years ago

for anyone who may wants to use react-native-fetch-blob with expo. expo is not compatible with any other package which requires react-native link command. there is a way discussed in expo documentation called expo-detach which allows you integrate native modules with expo.

leanminmachine commented 7 years ago

So is there really no possible alternative libraries to be used to integrate react-native with firebase if im on Expo other than to detach my Expo project :(

cloudonshore commented 7 years ago

@leanminmachine you can also base64 encoding option in the expo v18 ImagePicker (https://docs.expo.io/versions/v18.0.0/sdk/imagepicker.html#content), and then write the base64 string to firebase storage. Something like this:

import { ImagePicker } from 'expo'
import firebase from 'firebase'
async function takeAndUploadPhotoAsync() {
    const result = await ImagePicker.launchCameraAsync({
        base64: true
    })
   const imagesRef = firebase.storage().ref('/images')
   imagesRef.child('my_pic.jpg').putString(result.base64, 'base64').then(snapshot => {
       console.log("uploaded image!")
   })
}
rhenmark commented 6 years ago

@cloudonshore I tried to use the base64 parameter but it return an error that value did not match as base64. Did you try it?

cloudonshore commented 6 years ago

@rhenmark I have run into that error. For some reason I get it with expo on my ipad but not on my iphone.

I've found a workaround. Firebase storage API's handling of byte arrays seems to be more robust than it's handling of base64 strings. The base64-js npm package has a toByteArray method that works for me.

import { ImagePicker } from 'expo'
import firebase from 'firebase'
import b64 from 'base64-js'

async function takeAndUploadPhotoAsync() {
    const result = await ImagePicker.launchCameraAsync({
        base64: true
    })
   const byteArray = b64.toByteArray(result.base64)
   const metadata = {contentType: 'image/jpg'};
   firebase.storage().ref('/images').child('my_pic.jpg').put(byteArray, metadata).then(snapshot => {
       console.log("uploaded image!")
   })
}
Daveyjonez commented 6 years ago

@cloudonshore When I try your posted code, I get the error

Can currently only create a Blob from other Blobs

Also, how would you read that byte array back into an <Image> from firebase?

borch84 commented 5 years ago

I was able to workaround this, by not using Blob. const buffer = Buffer.from(this.state.base64,'base64');

Storage.put('file.jpeg',buffer,{contentType: 'image/jpeg'}) //we need to save the file in base64
    .then (result => console.log(result))
    .catch(err => console.log('error: '+err));

I am working with Expo Client.