1

I have a frontend with React native and I implemented the following:

import React, {Component} from 'react';
import Config from 'react-native-config';
import {
  Button,
  Alert,
  Image,
  Text,
  View,
  StyleSheet,
  TouchableOpacity,
  Platform,
  CameraRoll,
} from 'react-native';
import {Container, Content, Icon} from 'native-base';
import {RNCamera} from 'react-native-camera';
import {SubHeader} from '../../components/headers';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    backgroundColor: 'black',
  },
  preview: {
    flex: 1,
    justifyContent: 'flex-end',
    alignItems: 'center',
  },
  capture: {
    flex: 0,
    backgroundColor: '#fff',
    borderRadius: 5,
    padding: 15,
    paddingHorizontal: 20,
    alignSelf: 'center',
    margin: 20,
  },
});

export default class MainScreen extends Component {
  constructor(props) {
    super(props);
    this.state = {
      imageUri: null,
    };
  }

  test = async () => {
    if (this.camera) {
      const data = await this.camera.takePictureAsync({
        quality: 0.5,
        base64: true,
      });

      const photo = {
        name: data.fileName,
        type: data.type,
        uri:
          Platform.OS === 'android'
            ? data.uri
            : data.uri.replace('file://', ''),
      };

      this.setState({imageUri: data.uri}); //preview
      const fdata = new FormData();
      fdata.append('file', photo);

      try {
        let response = await fetch(`${Config.BASE_URL}/scan`, {
          method: 'POST',
          body: JSON.stringify(fdata),
          //body: fdata //this launches a connection error
        });
        const res = await response.json();

        return res;
      } catch (error) {
        console.error(error);
      }
    } else {
      Alert.alert('debug', 'There is no camera');
    }
  };

  render() {
    const {navigate} = this.props.navigation;

    return (
          <View style={styles.container}>
            <RNCamera
              ref={ref => {
                this.camera = ref;
              }}
              style={styles.preview}
              type={RNCamera.Constants.Type.back}
              flashMode={RNCamera.Constants.FlashMode.off}
              captureAudio={false}
              androidCameraPermissionOptions={{
                title: 'Permission to use camera',
                message: 'We need your permission to use your camera',
                buttonPositive: 'Ok',
                buttonNegative: 'Cancel',
              }}
              onGoogleVisionBarcodesDetected={({barcodes}) => {
                console.log(barcodes);
              }}
            />
            <View>
              <TouchableOpacity
                onPress={this.test.bind(this)}
                style={styles.capture}>
                <Icon type="FontAwesome" ios="camera" android="camera" />
              </TouchableOpacity>
            </View>
          </View>

           //preview
          <Image
            style={{width: 66, height: 58}}
            source={{
              uri: this.state.imageUri,
            }}
          />
        </View>
    );
  }
}

On the backend with nodeJs express and multer:

app.post('/scan', uploader.upload.single('file'), ScanController.scan);

Multer is well implemented because it is working with postman and with frontend web application fucntionalities.

the image is shown on the android device, but I am getting always an undefined object on the backend, i do not know how to send this because is on base 64, How can I send it or receive correctly?

burdk
  • 79
  • 12

1 Answers1

1

There is an open issue See here on react native about this, but I found a nice solution using rn-fetch-blob

as you may see in the documentation, you can implement the following:

First, delete the FormData instance, then change the fetch for RNFetchBlob.fetch

Code as follows

upload = async () => {
    let ret = await RNFetchBlob.fetch(
      'POST',
      `${Config.BASE_URL}/scan`,
      {
        'Content-Type': 'multipart/form-data',
      },
      [
        {
          name: 'file',
          filename: Date.now() + '.png',
          type: 'image/png',
          data: RNFetchBlob.wrap(data.uri),
        },
      ],
    );
    return ret;
  };

As you see, there is an array, where you can add the objects.

Multer implementation and RNCamera stays the same.

Hope this could be useful to someone!

burdk
  • 79
  • 12