Noitidart
Noitidart

Reputation: 37328

Uploading blob/file in react-native, contents is empty

I am able to succesfully upload a blob with proper contents from my web browser, but when I do it from react-native, the upload file is empty. Here is the code:

    async function doit() {
        const data = new FormData();
        data.append('str', 'strvalue');
        data.append(
          'f',
          new File(['foo'], 'foo.txt', {type: 'text/plain'}),
        );

        await fetch('http://localhost:3002/upload', {
            method: 'POST',
            body: data
          });
    }

However doing this same code from react-native, it uploads, but the file is empty.

Here is the node.js server I am using to test this. Loading http://localhost:3002 gives you a button called "upload it". Clicking it does the upload from the web. Screenshots of results are below.

var multiparty = require('multiparty');
var http = require('http');

http
  .createServer(function (req, res) {
    if (req.url === '/upload' && req.method === 'POST') {
      console.log('multipart here');
      var form = new multiparty.Form();

      form.parse(req, function (err, fields, files) {
        console.log(require('util').inspect({ fields, files }, false, null, true));
        res.setHeader('Content-Type', 'application/json');
        res.end(JSON.stringify({ bar: true }));
      });

      return;
    }

    console.log('here');
    // show a file upload form
    res.writeHead(200, { 'content-type': 'text/html' });
    res.end(
        `
        <script>
        async function doit() {
            const data = new FormData();
            data.append('str', 'strvalue');
            data.append(
              'f',
              // new File([new Blob(['asdf'], {type : 'text/plain'})], 'filename.txt'),
              new File(['foo', 'what', 'the', 'hell'], 'foo.txt', {type: 'text/plain'}),
            );

            const res = await fetch('http://localhost:3002/upload', {
                method: 'POST',
                body: data
              });
              console.log(JSON.stringify(res, null, 4));
        }
        document.addEventListener('DOMContentLoaded', () => {
            document.getElementById('b').addEventListener('click', doit, false)
        }, false);
        </script>
        <button type="button" id="b">upload it</button>
        `
    );
  })
  .listen(3002);

From web browser we see the node server logs this, notice file size is 14.

web browser upload shows file size of 14 in node server

However from react-native we see file size is 0:

enter image description here

Upvotes: 3

Views: 5797

Answers (1)

Ajin Kabeer
Ajin Kabeer

Reputation: 2186

I faced the same problem recently while posting an image from a react-native app to a server. However, I was able to make it work by appending the name and type of the file to the formData instance.

Here, the uri argument to uploadImageAsync is passed as a route parameter from the previous screen.

const uploadImageAsync = (uri: string) => {
  const apiUrl = "https://www.yourserver.com/image";
  let uriParts = uri.split(".");
  let fileType = uriParts[uriParts.length - 1];
  let formData = new FormData();
  formData.append("img", {
    uri,
    name: `photo.${fileType}`,
    type: `image/${fileType}`,
  });

  formData.append("description", "HEY");
  let options = {
    method: "POST",
    body: formData,
    headers: {
      Accept: "application/json",
      "Content-Type": "multipart/form-data",
      Authorization: "Bearer " + accessToken,
    },
  };
  return fetch(apiUrl, options);
};

Here is the Image configuration.

 const photoData = await camera.takePictureAsync({
      base64: true,
      exif: false,
    });

Upvotes: 5

Related Questions