3

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

1 Answer 1

5

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,
    });
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you Ajin! I will try this out and let you know how it went and then accept solution then! I see you had to make a uri of the image first, and not a blob? So I'll probably have to do URL.createObjectUrl(blob) and then pass this as the uri?
Yes, I had to make the uri first. This URL.createObjectUrl(blob) should work. Please let me know.
For sure man will let you know, got some other hot tasks that came up today. Will for sure get back to this though.
Had the same problem. Spent 5 hours today trying to understand the problem. When making the request from the HTTP client the file size was correct, but from react-native it was always 0. Adding the base64 image directly to the form data solved it. Thanks!
Glad it helped.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.