react-native-mqtt-file-transfer v0.2.5
ReactNativeMqttFileTransfer
ReactNativeMqttFileTransfer is an Expo Module that enables efficient and flexible file transfer over MQTT in React Native (Expo) apps. It supports both JavaScript-side and native-side file chunking, allowing you to send arbitrarily large files in small increments. It also tracks transfer progress and MQTT connection state in real time, so your UI can remain responsive.
Table of Contents
- Features
- Installation
- Configuration
- Usage
- API Reference
- Memory/Performance Tips
- Contributing
- Testing with Example App
- License
Features
- MQTT Connection Management: Connect to brokers supporting
mqtt
,mqtts
,ws
, orwss
. - File Transfer: Send files with:
- Native chunking: the module itself splits the file.
- Sending a single chunk: your app iterates chunks and calls native once per chunk.
- Progress Events: Real-time “onFileTransferProgress” with chunk index, total chunks, and percentage.
- Connection Events: Real-time “onMqttStateChanged” (connected/disconnected).
- Flexible Encoding: Out-of-the-box Base64 or UTF-8.
- Test Message Publishing: Quickly verify MQTT connectivity via a small sample message.
Installation
- Install from npm (or your private registry):
npm install react-native-mqtt-file-transfer # or yarn add react-native-mqtt-file-transfer
- Prebuild / Rebuild if using managed Expo:
or if using a bare React Native project, standard Gradle iOS/Android builds apply.npx expo prebuild
Configuration
Android
Some helpful tips on how to develop the Android part of this library:
- In Android Studio, you want to open the
example/android
folder, not theandroid
folder; - If there are Gradle errors, make sure that the Gradle JDK you selected is correct, e.g. Java 17 could be good. Change this in Android Studio -> Settings -> Build, Execution, Deployment -> Build Tools -> Gradle;
- Remember that the logs are in the
Logcat
tab of Android Studio, not in the terminal; - If you want to debug the native code, add breakpoints in the code, start it using
npx expo run:android
, and then in Android Studio there is a button 'Attach debugger to Android process' (a green bug with a phone icon).
iOS
Some helpful tips on how to develop the iOS part of this library:
- Xcode does not sync files changes such as creating or deleting files, from the file system automatically, so it's best to only make changes in Xcode and not another editor;
- To open the project in iOS, run
open ios/<MODULENAME>.xcworkspace
in the example folder, then in Xcode navigate to Pods -> Development Pods -> -> Module.swift; - If you want to debug the native code, add breakpoints in the code, start it using
npx expo run:ios
, and then in Xcode click on Debug -> Attach to Process -> (likely targets); - You might need to run
pod install
in theios
folder; - If you want to test on a physical device, run
npx expo run:ios --device
and make sure that the device is connected with a cable. Also, you need to trust the developer on the device, go to General -> VPN & Device Management -> Developer App if you are prompted to trust the developer.
Usage
Import and Setup
import ReactNativeMqttFileTransfer from 'react-native-mqtt-file-transfer';
Initialize MQTT
await ReactNativeMqttFileTransfer.initializeMqtt(
scheme, // e.g. 'mqtt', 'mqtts', 'ws', 'wss'
host, // 'broker.emqx.io'
port, // e.g. 1883 for mqtt, 9001 for ws
path // optional, only needed if scheme is 'ws' or 'wss'; e.g. '/mqtt'
);
- scheme:
'mqtt' | 'mqtts' | 'ws' | 'wss'
- path: only required for WebSocket-based connections.
Sending Files
Key Parameters:
- filePath: Local file path on the device (e.g., from DocumentPicker).
- encoding:
'base64'
or'utf8'
or'none'
. - destinationTopic: MQTT topic to publish to.
- chunkSize: Byte size for splitting data (e.g., 64KB, 256KB).
- chunkIndex (optional): If provided, only that chunk is sent; if omitted, the module automatically does native chunking.
Native Chunking
Let the native code handle reading and splitting your file. Omit chunkIndex
:
await ReactNativeMqttFileTransfer.sendFile(
filePath,
'base64',
'my/topic',
64_000, // chunkSize in bytes
undefined, // no chunkIndex => native chunking
);
JS Chunking
Split the file in JavaScript. For each chunk, pass the chunkIndex:
const totalChunks = Math.ceil(fileSize / chunkSizeInBytes);
for (let i = 0; i < totalChunks; i++) {
await ReactNativeMqttFileTransfer.sendFile(
filePath,
'base64',
'my/topic',
chunkSizeInBytes,
i
);
}
Your app fully controls the iteration logic.
Publish a Test Message
await ReactNativeMqttFileTransfer.publishTestMessage('my/test');
Sends a small message ("Hello from Kotlin!"
on Android or "Hello from Swift!"
on iOS) to quickly confirm connectivity.
Listening for Events
Two main events:
1. onMqttStateChanged
:
- { connected: boolean }
2. onFileTransferProgress
:
- { chunkIndex: number, totalChunks: number, percentage: number }
Example using expo-modules-core
EventEmitter
:
import { EventEmitter } from 'expo-modules-core';
import ReactNativeMqttFileTransfer from 'react-native-mqtt-file-transfer';
useEffect(() => {
const emitter = new EventEmitter(ReactNativeMqttFileTransfer);
// Connection changes
const connSub = emitter.addListener('onMqttStateChanged', (event) => {
console.log('MQTT is now', event.connected ? 'connected' : 'disconnected');
});
// Transfer progress
const progressSub = emitter.addListener('onFileTransferProgress', (progress) => {
console.log(
`Sending chunk ${progress.chunkIndex+1}/${progress.totalChunks} (${progress.percentage.toFixed(1)}%)`
);
});
return () => {
connSub.remove();
progressSub.remove();
};
}, []);
API Reference
1. initializeMqtt(scheme: string, host: string, port: number, path?: string)
Initializes the MQTT client.
- scheme:
'mqtt' | 'mqtts' | 'ws' | 'wss'
- host: e.g.
'broker.emqx.io'
- port: e.g.
1883
for tcp,8883
for ssl,9001
for ws,443
for wss - path: Optional string for WS subpath. If not provided for
ws|wss
, defaults to'/mqtt'
.
2. sendFile(filePath: string, encoding: string, destinationTopic: string, chunkSize: number, chunkIndex?: number)
Sends a file or file chunk.
- filePath: Local device path.
- encoding:
'base64' | 'utf8' | 'none'
- destinationTopic: MQTT topic.
- chunkSize: Byte size for each chunk.
- chunkIndex: If provided, only that chunk is read/sent; otherwise, the module streams the file.
3. publishTestMessage(topic: string)
Publishes a small test string to confirm connectivity.
4. Events
onMqttStateChanged
→{ connected: boolean }
onFileTransferProgress
→{ chunkIndex: number, totalChunks: number, percentage: number }
Memory/Performance Tips
- Reduce Chunk Size if you see
OutOfMemoryError
. - Avoid Base64 if your broker and subscriber can handle raw binary (
'none'
or'raw'
encoding). - Use Native Chunking to avoid bridging large file data through JS.
- If chunking in JS, add a brief delay (
await new Promise(r => setTimeout(r, 50))
) after each chunk to let GC catch up.
Contributing
- Fork this repository.
- Create a feature branch (
git checkout -b feature/newFeature
). - Commit your changes.
- Open a pull request to discuss and merge your work.
We welcome bug reports, suggestions, and pull requests!
Testing with the example app
- On the root folder, run
npm install && npm run build
- Go to the example folder, run
npm install && npx expo run:ios
ornpm install && npx expo run:android
NPM
Repo in npm https://www.npmjs.com/package/react-native-mqtt-file-transfer
Steps to publish to npm:
1. change version in package.json "version": "0.1.1"
2. npm login
3. npm publish
Full publish guide https://zellwk.com/blog/publish-to-npm/
License
ReactNativeMqttFileTransfer is released under the MIT License. See the LICENSE file for details.