Skip to content

Instantly share code, notes, and snippets.

@nandorojo
Created May 2, 2019 23:30
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save nandorojo/c641c176a053a9ab43462c6da1553a1b to your computer and use it in GitHub Desktop.
Save nandorojo/c641c176a053a9ab43462c6da1553a1b to your computer and use it in GitHub Desktop.
Upload a file to your server using react native / expo.
/*
IF YOU WANT TO UPLOAD ONE FILE, USE THE CODE BELOW.
SEE THE BOTTOM OF THE GIST TO SEE HOW TO UPLOAD MULTIPLE FILES.
HERE'S AN EXAMPLE SOMEONE MADE USING CLOUDINARY: https://gist.github.com/jamielob/5c1a5dc84e50e4507b71299d993dffec
*/
// 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, 'upload 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);
};
}
// REPLACE #4 WITH THE CODE BELOW IF YOU'RE UPLOADING AN ARRAY OF MULTIPLE FILES
// 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
});
})
@Chris-vermersch
Copy link

[SyntaxError: Unexpected token < in JSON at position 0], how fixe this ? ^^'

@nandorojo
Copy link
Author

Make sure you replace the places that have comments

@Prenam
Copy link

Prenam commented Apr 22, 2021

Hi, I just want to know how to call the function inside a TouchableOpacity to start uploading pdf files. My main struggle is that I don't know which one of these bunch of methods is the one to call from screen like an arrow function for example. I tried to wrap all these inside a function, and called it inside my TouchableOpacity but don't get a reponse.

@stharvey
Copy link

stharvey commented Nov 30, 2022

Thanks for this code.

I have implemented this in my expo app to use for video/image uploads (currently tested only on Android).

The actual upload works correctly however the xhr.upload.onprogress callback is reporting inaccurate data. For example, when uploading a largish file (~70mb) this returns 0%, then 69%, then 98%, then 100% - this is returned over the first few seconds even though the actual file upload takes ~1-2 minutes.

Do you know what might be going on with that?

const formData = new FormData();
  formData.append("FileInput", {
          uri: uri,
          type: "video/" + ext,
          name: fileName,
        });

          const xhr = new XMLHttpRequest();

          xhr.open("POST", url);
      
          xhr.onload = () => {
            const response = JSON.parse(xhr.response);
            resolve(true);
          };
          xhr.onerror = (e) => {
            console.log(e, "upload failed");
          };
          xhr.ontimeout = (e) => {
            console.log(e, "upload timeout");
          };

          xhr.send(formData);

          if (xhr.upload) {
            xhr.upload.onprogress = ({ total, loaded }) => {
              uploadProgress = Math.round((loaded / total) * 100);
              console.log(uploadProgress, total, loaded);
            };
          }

@nandorojo
Copy link
Author

I haven’t seen this in years. That said, I never managed to get that function working properly I believe. Maybe there’s more to how it works.

@stharvey
Copy link

Thanks.

I've implemented the same upload but using axios and I get exactly the same issue (onUploadProgress reporting 100% much more quickly than the upload actually takes). I'll do some more digging.

@stharvey
Copy link

stharvey commented Nov 30, 2022

Hello again, I've figured this out. Just in case this helps someone else:

The issue was occurring when running a development bundle on a metro server - axios/xhr was reporting on the status of the upload of the file to the metro proxy rather than to it's final destination on the net.

When I created an apk build everything worked correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment