I am developing a app where i need to upload an image to the server. Based on the image i get a response which i need to render?.

Can you please help me how to upload an image using react-native?.

Solution 1

There is file uploading built into React Native.

Example from React Native code:

var photo = {
    uri: uriFromCameraRoll,
    type: 'image/jpeg',
    name: 'photo.jpg',
};

var body = new FormData();
body.append('authToken', 'secret');
body.append('photo', photo);
body.append('title', 'A beautiful photo!');

var xhr = new XMLHttpRequest();
xhr.open('POST', serverURL);
xhr.send(body);

Solution 2

My solution is using fetch API and FormData.

Tested on Android.

const file = {
  uri,             // e.g. 'file:///path/to/file/image123.jpg'
  name,            // e.g. 'image123.jpg',
  type             // e.g. 'image/jpg'
}

const body = new FormData()
body.append('file', file)

fetch(url, {
  method: 'POST',
  body
})

Solution 3

I wrote something like that. Check out https://github.com/kamilkp/react-native-file-transfer

Solution 4

I have been struggling to upload images recently on react-native. I didn't seem to get the images uploaded. This is actually because i was using the react-native-debugger and network inspect on while sending the requests. Immediately i switch off network inspect, the request were successful and the files uploaded.

I am using the example from this answer above it works for me.

This article on github about the limitations of network inspect feature may clear things for you.

Solution 5

Just to build on the answer by Dev1, this is a good way to upload files from react native if you also want to show upload progress. It's pure JS, so this would actually work on any Javascript file.

(Note that in step #4 you have to replace the variables inside the strings with the type and file endings. That said, you could just take those fields out.)

Here's a gist I made on Github: https://gist.github.com/nandorojo/c641c176a053a9ab43462c6da1553a1b

1. for uploading one file:


// 1. initialize request
const xhr = new XMLHttpRequest();
// 2. open request
xhr.open('POST', uploadUrl);
// 3. set up callback for request
xhr.onload = () => {
    const response = JSON.parse(xhr.response);

    console.log(response);
    // ... do something with the successful response
};
// 4. catch for request error
xhr.onerror = e => {
    console.log(e, 'upload failed');
};
// 4. catch for request timeout
xhr.ontimeout = e => {
    console.log(e, 'cloudinary timeout');
};
// 4. create formData to upload
const formData = new FormData();

formData.append('file', {
    uri: 'some-file-path',          // this is the path to your file. see Expo ImagePicker or React Native ImagePicker
    type: `${type}/${fileEnding}`,  // example: image/jpg
    name: `upload.${fileEnding}`    // example: upload.jpg
});
// 6. upload the request
xhr.send(formData);
// 7. track upload progress
if (xhr.upload) {
    // track the upload progress
    xhr.upload.onprogress = ({ total, loaded }) => {
        const uploadProgress = (loaded / total);
        console.log(uploadProgress);
    };
}


2. uploading multiple files Assuming you have an array of files you want to upload, you'd just change #4 from the code above to look like this:


// 4. create formData to upload
const arrayOfFilesToUpload = [
    // ...
];
const formData = new FormData();

arrayOfFilesToUpload.forEach(file => {
    formData.append('file', {
        uri: file.uri,                  // this is the path to your file. see Expo ImagePicker or React Native ImagePicker
        type: `${type}/${fileEnding}`,  // example: image/jpg
        name: `upload.${fileEnding}`    // example: upload.jpg
    });
})

Solution 6

A couple of potential alternatives are available. Firstly, you could use the XHR polyfill:

http://facebook.github.io/react-native/docs/network.html

Secondly, just ask the question: how would I upload a file in Obj-C? Answer that and then you could just implement a native module to call it from JavaScript.

There's some further discussion on all of this on this Github issue.

Solution 7

Tom's answer didn't work for me. So I implemented a native FilePickerModule which helps me choose the file and then use the remobile's react-native-file-transfer package to upload it. FilePickerModule returns the path of the selected file (FileURL) which is used by react-native-file-transfer to upload it. Here's the code:

var FileTransfer = require('@remobile/react-native-file-transfer');
var FilePickerModule = NativeModules.FilePickerModule;

      var that = this;
      var fileTransfer = new FileTransfer();
      FilePickerModule.chooseFile()
      .then(function(fileURL){
        var options = {};
        options.fileKey = 'file';
        options.fileName = fileURL.substr(fileURL.lastIndexOf('/')+1);
        options.mimeType = 'text/plain';
        var headers = {
          'X-XSRF-TOKEN':that.state.token
        };
        options.headers = headers;
        var url = "Set the URL here" ;
        fileTransfer.upload(fileURL, encodeURI(url),(result)=>
        {
              console.log(result);
          }, (error)=>{
              console.log(error);
          }, options);
     })

Solution 8

In my opinion, the best way to send the file to the server is to use react-native-fs package, so install the package with the following command

npm install react-native-fs

then create a file called file.service.js and modify it as follow:

import { uploadFiles } from "react-native-fs";

export async function sendFileToServer(files) {
        return uploadFiles({
            toUrl: `http://xxx/YOUR_URL`,
            files: files,
            method: "POST",
            headers: { Accept: "application/json" },
            begin: () => {
                // console.log('File Uploading Started...')
            },
            progress: ({ totalBytesSent, totalBytesExpectedToSend }) => {
                // console.log({ totalBytesSent, totalBytesExpectedToSend })
            },
        })
            .promise.then(({ body }) => {
                // Response Here...
                // const data = JSON.parse(body); => You can access to body here....
            })
            .catch(_ => {
               // console.log('Error')
            })
    }

NOTE: do not forget to change the URL.

NOTE: You can use this service to send any file to the server.

then call that service like the following:

var files = [{ name: "xx", filename:"xx", filepath: "xx", filetype: "xx" }];
await sendFileToServer(files)

NOTE: each object must have name,filename,filepath,filetype

Solution 9

Upload Files : using expo-image-picker npm module. Here we can upload any files or images etc. The files in a device can be accessed using the launchImageLibrary method. Then access the media on that device.

import * as ImagePicker from "expo-image-picker";

const loadFile = async () => {
  let result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.All,
    aspect: [4, 3],
  });
  return <Button title="Pick an image from camera roll" onPress={loadFile} />
}

The above code used to access the files on a device.

Also, use the camera to capture the image/video to upload by using launchCameraAsync with mediaTypeOptions to videos or photos.