A hook for uploading files using multipart form data with React Native.

Overview

react-native-use-file-upload

A hook for uploading files using multipart form data with React Native. Provides a simple way to track upload progress, abort an upload, and handle timeouts. Written in TypeScript and no dependencies required.

npm version

example app

Installation

yarn add react-native-use-file-upload

Example App

There is an example app in this repo as shown in the above gif. It is located within example and there is a small node server script within example/server here. You can start the node server within example using yarn server. The upload route in the node server intentionally throttles the upload requests. You can read more about this in the FAQs below.

Usage

import useFileUpload, { UploadItem } from 'react-native-use-file-upload';

// Used in optional type parameter for useFileUpload
interface Item extends UploadItem {
  progress?: number;
}

// ...
const [data, setData] = useState<Item[]>([]);
// The generic type param below for useFileUpload is optional
// and defaults to UploadItem. It should inherit UploadItem.
const { startUpload, abortUpload } = useFileUpload<Item>({
  url: 'https://example.com/upload',
  field: 'file',
  // Below options are optional
  method: 'POST',
  headers,
  timeout: 60000,
  onProgress,
  onDone,
  onError,
  onTimeout,
});

const onPressUpload = async () => {
  const promises = data.map((item) => startUpload(item));
  // Use Promise.all instead if you want to throw an error from a timeout or error.
  // As of October 2022 you have to polyfill allSettled in React Native.
  const result = await Promise.allSettled(promises);
};

Methods

startUpload

Start a file upload for a given file. Returns a promise that resolves with OnDoneData or rejects with OnErrorData.

// Objects passed to startUpload should have the below shape at least (UploadItem type)
startUpload({
  name: 'file.jpg',
  type: 'image/jpg',
  uri: 'file://some-local-file.jpg',
});

abortUpload

Abort a file upload for a given file. The promise from startUpload gets rejected and onError runs if present.

// Pass the uri of a file that started uploading
abortUpload('file://some-local-file.jpg');

Options

Name Type Required Description
url string Required The URL to send the request to.
field string Required The field name that will be used for the file in FormData.
method string Optional The HTTP method for the request. Defaults to "POST".
headers Headers Optional Option for passsing in requst headers.
const headers = new Headers();
headers.append('Authorization', 'foo');
useFileUpload({ headers });
timeout number Optional The timeout value for the request in milliseconds.
onProgress function Optional Callback when a request times out for a given file. It receives 1 argument of this shape -
// OnProgressData type
{
  item: UploadItem; // or a type that inherits UploadItem
  event: ProgressEvent<EventTarget>;
};
// event is the XMLHttpRequest progress event object and it's shape is -
{
  loaded: number,
  total: number
}
onDone function Optional Callback on request completion for a given file. It receives 1 argument of this shape -
// OnDoneData type
{
  item: UploadItem; // or a type that inherits UploadItem
  responseBody: string; // eg "{\"foo\":\"baz\"}" (JSON) or "foo"
  responseHeaders: string;
}
onError function Optional Callback when a request error happens for a given file. It receives 1 argument of this shape -
// onErrorData type
{
  item: UploadItem; // or a type that inherits UploadItem
  error: string;
}
onTimeout function Optional Callback when a request error happens for a given file. It receives 1 argument of this shape -
// OnErrorData type
{
  item: UploadItem; // or a type that inherits UploadItem
  error: string;
  timeout: boolean; // true here
}

FAQs

Do requests continue when the app is backgrounded?

Requests will time out if you background the app. This can be addressed by using react-native-background-upload.

The React Native team did a a heavy lift to polyfill and bridge XMLHttpRequest to the native side for us. There is an open PR in React Native to allow network requests to run in the background for iOS. There are plans to have a similar PR for Android as well. react-native-background-upload is great but if backgrounding can be supported without any native dependencies it is a win for everyone.

Why send 1 file at a time instead of multiple in a single request?

It is possible to to send multiple files in 1 request. There are downsides to this approach though and the main one is that it is slower. A client has the ability to handle multiple server connections simultaneously, allowing the files to stream in parallel. This folds the upload time over on itself.

Another downside is fault tolerance. By splitting the files into separate requests, this strategy allows for a file upload to fail in isolation. If the connection fails for the request, or the file is invalidated by the server, or any other reason, that file upload will fail by itself and won't affect any of the other uploads.

How does the local node server throttle the upload requests?

The local node server throttles the upload requests to simulate a real world scenario on a cellular connection or slower network. This helps test out the progress and timeout handling on the client. It does this by using the node-throttle library. See the /upload route in here for the details.

How do I bypass the throttling on the local node server?

Set the url in useFileUpload to http://localhost:8080/_upload.

The onDone and promise from startUpload take awhile to resolve in the example app.

This is because of the throttling and can be bypassed.

Why is type and name required in the UploadItem type?

This is because of how React Native abstracts away setting the content-disposition request header for us in their polyfill for FormData. You can see here how that is being done in the getParts function.

License

MIT


Made with create-react-native-library

You might also like...
OAuth login for React Native
OAuth login for React Native

react-native-simple-auth OAuth login for React Native Screencast Install Providers Setup Usage License Screencast iOS Android Source of example app: h

lazyload for react native

react-native-lazyload A `lazyload` components suit for React Native. Install npm install react-native-lazyload Components Component Description Lazyl

node's net api in react-native

TCP in React Native node's net API in React Native This module is used by Peel Install Create a new react-native project. Check react-native getting s

node's dgram for react-native

react-native-udp React Native UDP socket API for Android & iOS. It allows you to create UDP sockets, imitating Node's dgram API functionalities (check

React Native AWS Cognito JS SDK

This library is deprecated. It was merged into aws cognito identity js and finally into: https://github.com/aws-amplify/amplify-js. The amplify librar

A react native wrapper for socket.io-client-swift

🚨 this library is not maintained anymore! A React Native wrapper for the Socket.io Swift Library The wrapped 'Socket.IO-Client-Swift' can be found he

A plugin for file upload on react-native

react-native-file-upload React Native latest version had support file upload, the package is deprecated, detail see #4 #7. A file upload plugin for re

A React Native wrapper for AWS iOS/Android S3 SDK.

React Native AWS S3 A React Native wrapper for AWS iOS/Android S3 SDK. We currently implements TransferUtility, it allow you to upload / download task

A react native version of backbone model

react-native-backbone As react native does not support Node.js HTTP module, react-native-backbone helps you to connect to your REST api or localStorag

Releases(0.1.6)
  • 0.1.6(Dec 27, 2022)

    What's Changed

    • Update example by @rossmartin in https://github.com/rossmartin/react-native-use-file-upload/pull/7

    Full Changelog: https://github.com/rossmartin/react-native-use-file-upload/compare/0.1.5...0.1.6

    Source code(tar.gz)
    Source code(zip)
  • 0.1.5(Nov 28, 2022)

    What's Changed

    • Remove node throttle by @rossmartin in https://github.com/rossmartin/react-native-use-file-upload/pull/6

    Full Changelog: https://github.com/rossmartin/react-native-use-file-upload/compare/0.1.4...0.1.5

    Source code(tar.gz)
    Source code(zip)
  • 0.1.4(Nov 16, 2022)

    What's Changed

    • Update readme by @rossmartin in https://github.com/rossmartin/react-native-use-file-upload/pull/5

    Full Changelog: https://github.com/rossmartin/react-native-use-file-upload/compare/0.1.3...0.1.4

    Source code(tar.gz)
    Source code(zip)
  • 0.1.3(Nov 11, 2022)

    What's Changed

    • Make useFileUpload generic by @rossmartin in https://github.com/rossmartin/react-native-use-file-upload/pull/4

    Full Changelog: https://github.com/rossmartin/react-native-use-file-upload/compare/0.1.2...0.1.3

    Source code(tar.gz)
    Source code(zip)
  • 0.1.2(Nov 9, 2022)

    What's Changed

    • Reject promise when request is aborted by @rossmartin in https://github.com/rossmartin/react-native-use-file-upload/pull/3

    Full Changelog: https://github.com/rossmartin/react-native-use-file-upload/compare/0.1.1...0.1.2

    Source code(tar.gz)
    Source code(zip)
  • 0.1.1(Nov 6, 2022)

    What's Changed

    • Fix lint and add CI workflow by @rossmartin in https://github.com/rossmartin/react-native-use-file-upload/pull/2

    New Contributors

    • @rossmartin made their first contribution in https://github.com/rossmartin/react-native-use-file-upload/pull/2

    Full Changelog: https://github.com/rossmartin/react-native-use-file-upload/compare/0.1.0...0.1.1

    Source code(tar.gz)
    Source code(zip)
  • 0.1.0(Oct 30, 2022)

Owner
Ross Martin
Ross Martin
A React Native module to upload files and camera roll assets.

react-native-uploader A React Native module for uploading files and camera roll assets. Supports progress notification. Install iOS npm install react-

Adam Roth 513 Sep 26, 2022
Upload files in your React Native app even while it's backgrounded. Supports Android and iOS, including camera roll assets.

react-native-background-upload The only React Native http post file uploader with android and iOS background support. If you are uploading large files

Vydia 651 Dec 29, 2022
react-native module to download and upload files

This module is deprecated. Use https://github.com/wkh237/react-native-fetch-blob or https://github.com/johanneslumpe/react-native-fs instead. react-na

Erdem BaÅŸeÄŸmez 105 Aug 9, 2022
A project committed to making file access and data transfer easier, efficient for React Native developers.

New Maintainers and Repository Location This repository no longer is the main location of "react-native-fetch-blob". The owners of this fork have agre

Ben Hsieh 2.6k Jan 7, 2023
XMPP library for React Native (iOS and Android native support)

react-native-xmpp An XMPP library for React Native. A simple interface for native XMPP communication. Both iOS and Android are supported. Demo XmppDem

Pavel Aksonov 301 Nov 29, 2022
Native file download utility for react-native

This repo is deprecated in favor of react-native-fs React Native File Download Native file download utility for react-native Note that does not suppor

Perry Poon 47 Apr 16, 2022
Communicate over ad hoc wifi using Multipeer Connectivity

react-native-multipeer Communicate over ad hoc wifi using Multipeer Connectivity. Known Issues Below is a list of known issues. Pull requests are welc

Loch Wansbrough 197 Dec 22, 2022
Animo-demo - Animo Self-Sovereign Identity Demo build using Aries Framework Javascript

Animo Self-Sovereign Identity Demo ✨ Hi there! Welcome to the repository of Anim

Animo 14 Dec 7, 2022
Meteor Reactivity for your React Native application :)

react-native-meteor Meteor-like methods for React Native. If you have questions, you can open a new issue in the repository or ask in the our Gitter c

inProgress 700 Dec 9, 2022
AWS SDK for React Native (developer preview)

Attention: Please use the AWS Amplify library for React Native development of new projects on AWS. We've also released a React Native starter kit at h

Amazon Archives 635 Dec 15, 2022