Wahyu Setiawan
Wahyu Setiawan

Reputation: 99

How to display image blob for react native

I try to show image in my react-native app. I've uploaded photo into my Firebase Storage and it's work. Then i try to display my image from Firebase Storage, but the file is blob. I want to convert blob to image but i don't know the syntax. Might be one of you could help me to solve this.

where should i place RNFetch blob? I've tried to place inside componentWillMount and it show error.

uploadImage(uri, mime = 'application/octet-stream') {
        return new Promise((resolve, reject) => {
            const uploadUri = uri
            let uploadBlob = null

            const imageRef = firebase.storage().ref('profileImg').child(`${this.state.user.uid}/Profile Image - ${this.state.user.uid}`)

            fs.readFile(uploadUri, 'base64')
            .then((data) => {
                return Blob.build(data, { type: `${mime};BASE64` })
            })
            .then((blob) => {
                uploadBlob = blob
                return imageRef.put(blob, { contentType: mime })
            })
            .then(() => {
                uploadBlob.close()
                return imageRef.getDownloadURL()
            })
            .then((url) => {
                console.log(url)
                resolve(url)
            })
            .catch((e) => {
                console.log(e)
                reject(e)
            })
        })
    }

    getProfileImage(){
        let options = {
        title: 'Choose Photo',
        storageOptions: {
        skipBackup: true,
        path: 'images'
      }
    };

    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 {
            let image_uri = { uri: 'data:image/jpeg;base64,' + response.data };
            this.uploadImage(response.uri)
            .then((url) => { 
                console.log('uploaded')
                this.setState({
                    image_uri: url,
                });
            })
            .catch((error) => console.log(error))
            firebase.auth().currentUser.updateProfile({
                photoURL: this.state.image_uri
            });
          }
      })
    }

Upvotes: 1

Views: 7240

Answers (3)

Omar Samman
Omar Samman

Reputation: 613

i had the same problem and the workaround that i implented was to put the file type in the State

in Constructor

constructor() {
    super();
    // we will change it to fill the image file type from response
    this.state = {
        fileType: ""
    };
}

and in the getImage() function we should change state to put the file type

getImage() {
    ImagePicker.showImagePicker(options, response => {
        console.log("Response = ", response);
        this.setState({
            fileType: response.type
        });
......... the rest of the code

and in uploadImage() you should put the mime to the fileType in state as implemented here

 uploadImage(uri, mime = this.state.fileType) {
    return new Promise((resolve, reject) => {
        const uploadUri =
            Platform.OS === "ios" ? uri.replace("file://", "") : uri;
        let uploadBlob = null;

        const imageRef = firebase
            .storage()
            .ref("images/")
            .child(Date.now());

        fs.readFile(uploadUri, "base64")
            .then(data => {
                return Blob.build(data, { type: `${mime};BASE64` });
            })
            .then(blob => {
                uploadBlob = blob;
                var metadata = {
                    contentType: mime
                };

                return imageRef.put(uri, metadata);
            })
            .then(() => {
                uploadBlob.close();
                return imageRef.getDownloadURL();
            })
            .then(url => {
                resolve(url);
            })
            .catch(error => {
                reject(error);
            });
    });
}

this is my first answer BTW

Upvotes: 3

Pritish Vaidya
Pritish Vaidya

Reputation: 22189

Right now, what you're trying to do is upload image to firebase by converting base64 to blob and getting the blob from success query and convert to base64 to display it again.

Since you're already using a promise, what you can do is check if the image has been uploaded successfully, then display the same base64 otherwise your original data.

// Default Image data
let image_uri = { uri: 'data:image/jpeg;base64,' + response.data };

this.uploadImage(response.uri)
            .then((url) => { 
                // Success, replace with base64 you've got
                console.log('uploaded')
                this.setState({
                    image_uri
                });
            })
            .catch(error => {
               this.setState({
                    image_uri: // SOME DEFAULT IMAGE VALUE
                });
            })

Upvotes: 0

Ada P
Ada P

Reputation: 39

This works for my case:

userPhoto is is a blob string.

  <img className="pic__photo" src={"data:image/png;base64," + userPhoto} />

Upvotes: 0

Related Questions