Android: Network Request Failed when trying to upload image with fetch

Viewed 3637

I'm trying to upload an image from storage to a restful API but I keep getting Network Request Failed on Android (which means the request doesn't even go through), haven't checked on iOS because I don't need that part yet. API is already working and has been tested with Postman.

The React Native code is:

  body.append('vehicles',{ 
    resource_id: 2,
    resource: 'vehicles',
    cat_file_id: fileId,
    active: 1,
    vehicles: photo, //<- photo value below
    name: 'vehicles',
    type: 'image/jpeg'
  })

  fetch(`${BASE_URL}/files`, {
    method: 'POST',
    headers: {
      'Content-Type': 'multipart/form-data',
      Accept: "*/*",
      Authorization: 'Bearer '+auth
    },
    body: body

  }).then(response => response.json())
  .then(response => {
    console.log('IMAGE RESPONSE', response)
  })
  .catch(error => console.log('ERROR', error))

The photo value looks like file:///storage/emulated/0/DCIM/...

The response:

ERROR TypeError: Network request failed
at XMLHttpRequest.xhr.onerror (fetch.umd.js:473)
at XMLHttpRequest.dispatchEvent (event-target-shim.js:818)
at XMLHttpRequest.setReadyState (XMLHttpRequest.js:574)
at XMLHttpRequest.__didCompleteResponse (XMLHttpRequest.js:388)
at XMLHttpRequest.js:501
at RCTDeviceEventEmitter.emit (EventEmitter.js:189)
at MessageQueue.__callFunction (MessageQueue.js:436)
at MessageQueue.js:111
at MessageQueue.__guard (MessageQueue.js:384)
at MessageQueue.callFunctionReturnFlushedQueue (MessageQueue.js:110)

On Postman the request looks something like this:

Headers

Body

Already tried:

  • Removing Accept header
  • Changing Accept value to 'application/json'
  • Removing file:// from the image url
  • Added android:usesCleartextTraffic="true" to the manifest

Already checked:

  • No values are null or undefined
  • There is a working internet connection, all other network requests on the app are working fine
  • The Auth is correct

React Native version is 0.61.5

5 Answers

I found one missing line in your code let formData = new FormData();. but not sure is that the exact issue here. By the way here is a sample working code from one of my project, and I customized it with your context.

  1. Add your authentication
  2. replace ImageURI with image path and URL_SAVE_IMAGE endpoint url

    const newImage = {
        resource_id: 2,
        resource: 'vehicles',
        cat_file_id: 1,
        active: 1,
        vehicles: ImageURI,
        name: "my_photo.jpg",
        type: "image/jpg",
    };
    
    let formData = new FormData();
    formData.append("vehicles", newImage);
    
    return fetch(URL_SAVE_IMAGE, {
        method: 'POST',
        headers: {
            "Content-Type": "multipart/form-data"
        },
        body: formData
    }).then(response => response.json());
    

it should work!

What is your fetch(${BASE_URL}/files` backend server .. This usually happens when trying to connect to the backend api on the localhost machine.. Even if you use the IP address of the localhost, it still persists, so it is better to use online server for testing or just use ngrok(https://ngrok.com/) to serve your backend localhost via internet.

in gradle.properties change the flipper version to 0.47.0

try with Xhr, it's working as expected!

const URL = "ANY_SERVER/upload/image"
  const xhr = new XMLHttpRequest();
  xhr.open('POST', url); // the address really doesnt matter the error occures before the network request is even made.
  const data = new FormData();
  data.append('image', { uri: image.path, name: 'image.jpg', type: 'image/jpeg' });

  xhr.send(data);
  xhr.onreadystatechange = e => {
    if (xhr.readyState !== 4) {
      return;
    }

    if (xhr.status === 200) {
      console.log('success', xhr.responseText);
    } else {
      console.log('error', xhr.responseText);
    }
  };

Nothing worked for me except using the Expo FileSystem uploadAsync

uploadImage = async ({ imageUri } }) => FileSystem.uploadAsync(
    apiUrl,
    imageUri,
    {
      headers: {
        // Auth etc
      },
      uploadType: FileSystem.FileSystemUploadType.MULTIPART,
      fieldName: 'files',
      mimeType: 'image/png',
    });

Note - imageUri in format of file:///mypath/to/image.png

Happy days!

Related