Chimezie Innocent I am Chimezie, a software developer based in Nigeria. I am highly skilled in HTML, CSS, and JS to build web-accessible and progressive apps. I'm also skilled with React for web, React Native for Android apps, and Tailwind CSS. I write technical articles, too.

How to fetch and handle blob data in React Native

14 min read 4178 109

How To Fetch And Handle Blob Data In React Native

Occasionally, when working with React Native, we might need to access our device’s file system to perform certain operations. These operations could include creating, saving, and editing a file, or uploading or downloading files from the cloud.

This is where the react-native-fs and react-native-blob-util packages come into play. These packages provide native file system access for React Native. In other words, they make file access and data transfer more accessible and efficient for React Native developers, especially for large files like blobs.

This article will explore how to manage cloud data in React Native by using these two packages to fetch and handle blobs, as well as to create, save, and read files. We will cover:

What is a blob?

Blob is short for “Binary Large Object.” This data type holds multimedia objects like images and videos, GIFs, and audio. It stores binary data as a single entity.

To download, upload, and read blobs in React Native, we can use either react-native-fs or react-native-blob-util. These packages give developers access to upload and download data directly to and from cloud storage, which — especially for large files like blobs — is more efficient.

Managing cloud data with react-native-fs

Before we begin looking at how to manage our cloud data with the react-native-fs package, let’s first see how it works locally — i.e., how we can create, read, and save files on our devices.

To install the package, run either of the two commands below in your terminal:

/* npm */
npm install react-native-fs

/* yarn */
yarn add react-native-fs

After installation, link the package to your project by running the command below:

react-native link react-native-fs

This will automatically add the react-native-fs package to your project. In a scenario where the automatic linking does not work for you for some reason, check the official docs to see how to manually link the package to your project.

Creating and saving files

To create a file, react-native-fs offers a method called writeFile. It allows us to write our files to a file path. The syntax is as follows:

writeFile(filepath, contents, encoding)

Let’s take a look at each component of this method:

  • filepath — the directory or absolute path in which you want to save your file
  • contents — the file content, or what you want to save
  • encoding — can be UTF-8, ASCII values, or the property you want to save your file as

See the code below for an example of creating and saving files with react-native-fs:

/* App.js */ 

import React, {useState} from 'react';
import {
  SafeAreaView,
  StyleSheet,
  Text,
  TextInput,
  View,
  TouchableOpacity,
  Alert,
} from 'react-native';
import {DocumentDirectoryPath, writeFile} from 'react-native-fs';

const App = () => {
  const [text, setText] = useState('');
  const filePath = `${DocumentDirectoryPath}/testing.txt`;

  const createFile = async () => {
    try {
      await writeFile(filePath, text, 'utf8');
      Alert.alert('File created successfully');
    } catch (e) {
      console.log('error', e);
    }
  };
  return (
    <SafeAreaView style={styles.parent}>
      <View style={styles.container}>
        <View style={styles.textInput}>
          <Text style={styles.title}>Enter text:</Text>
          <TextInput
            value={text}
            onChangeText={setText}
            style={styles.textArea}
            multiline
            textAlignVertical="top"
          />
        </View>
        <TouchableOpacity onPress={createFile} style={styles.button}>
          <Text style={styles.buttonText}>Create new file</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};
const styles = StyleSheet.create({
  parent: {
    flex: 1,
  },
  container: {
    padding: 16,
    flex: 1,
  },
  textInput: {
    flex: 1,
    paddingVertical: 16,
  },
  textArea: {
    height: 200,
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 5,
    padding: 16,
    fontSize: 18,
  },
  title: {
    color: '#fff',
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 16,
  },
  button: {
    borderRadius: 5,
    marginBottom: 20,
    backgroundColor: 'green',
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    textAlign: 'center',
    paddingVertical: 10,
  },
});
export default App;

In the code above, we are importing DocumentDirectoryPath and writeFile from our react-native-fs package. Using the DocumentDirectoryPath constant, we are getting the directory file path of where we want to save our file. Then, using the writeFile method, we are saving our file with the content of our input.

The image below shows what we should see before creating a file:

Phone Screen With Dark Grey Background. Top Third Of Screen Displays Prompt To Enter Text Above Empty Text Box. Bottom Of Screen Shows Green Button To Create New File

After saving the file, we should now see the following:

Same Image As Before, Now With Three Lowercase Letter T In Text Box, Keyboard Displayed At Bottom, And Popup Notification Confirming File Was Created Successfully With Ok Button To Dismiss Notification

Reading files with readDir and readFiles

In the previous section, we successfully created a new file that we called testing.txt. Now, we will go ahead and read the file. What this means is that we will be able to see a list of all the files that we created in our directory and view their contents as we select each one.

The react-native-fs package provides us with two methods — readDir and readFiles. Let’s see how to use each method to read our files.

Using the readDir method

The readDir method lets us read the contents of a path or absolute path. The syntax is as follows:

readDir(directorypath)

This method returns a promise that contains an array of objects with properties. These properties include:

  • ctime — the date that the file was created; this property is only available for iOS
  • mtime — the date that the file was last modified or changed
  • name — the name of the file or item
  • path — contains the absolute path of the file or item
  • size — shows the size of the file
  • isFile — a function that returns a boolean that shows if the item is a file or not
  • isDirectory — a function that returns a boolean that shows if a file is a directory or not

Consider the below:

/* App.js */

import React, {useState, useEffect} from 'react';
import {
SafeAreaView,
StyleSheet,
Text,
FlatList,
View,
TouchableOpacity,
} from 'react-native';
import {DocumentDirectoryPath, readDir} from 'react-native-fs';

const App = () => {
const [directory, setDirectory] = useState([]);

useEffect(() => {
const getDirectoryList = async () => {
try {
const pathList = await readDir(DocumentDirectoryPath);
setDirectory(pathList);
} catch (error) {
console(error);
}
};
getDirectoryList();
}, []);

const renderItem = ({item}) => (


{item.name}


);

return (


Files
{directory.length > 0 ? (
item.name}
/>
) : (
No files
)}


);
};
const styles = StyleSheet.create({
parent: {
flex: 1,
},
container: {
padding: 16,
flex: 1,
},
fileHeader: {
color: '#fff',
fontSize: 30,
marginBottom: 10,
borderColor: '#ccc',
paddingBottom: 10,
borderBottomWidth: 1,
},
list: {
marginVertical: 5,
paddingBottom: 12,
borderBottomWidth: 1,
borderColor: '#ccc',
},
listName: {
fontSize: 16,
},
});
export default App;

 

After running this code, here’s what you should see:
Phone Screen With Dark Grey Background Showing List Of Four Files

In the code above, we are using the try...catch method to read our directory path using the readDir method. Then, we set the response to the directory array in our state. Next, we mapped through the array using FlatList and rendered the list of files as shown in the image above.

Using the readFile method

The readFile method lets us read the contents of a file that we have saved. It also returns a promise containing an array of objects with properties, just like the readDir method. The syntax is as follows:

readFile(filename, encoding)

Let’s see an example of using the readFile method in the code below:

/* App.js */

import React, {useState, useEffect} from 'react';
import {
  SafeAreaView,
  StyleSheet,
  Text,
  FlatList,
  View,
  TouchableOpacity,
} from 'react-native';
import {DocumentDirectoryPath, readDir, readFile} from 'react-native-fs';

// component of the file we want to view
const ViewFile = ({content, onclose}) => {
  const [fileContent, setFileContent] = useState(null);
  useEffect(() => {
    const getContent = async () => {
      try {
          if (content.isFile()) {
          const response = await readFile(content.path, 'utf8');
          setFileContent(response);
        }
      } catch (error) {
        console.log(error);
      }
    };
    getContent();
    return () => getContent();
  }, []);

  return (
    <View style={styles.parent}>
      <View style={styles.container}>
        <View>
          <Text style={[styles.fileHeader, {textTransform: 'capitalize'}]}>
            {content.name.replace('.txt', '')}
          </Text>
        </View>
        <Text style={styles.content}>{fileContent}</Text>
      </View>
      <TouchableOpacity style={styles.button} onPress={onclose}>
        <Text style={styles.buttonText}>Go Back</Text>
      </TouchableOpacity>
    </View>
  );
};

// main component
const App = () => {
  const [directory, setDirectory] = useState([]);
  const [readFIle, setReadFile] = useState(null);
  const [checkContent, setCheckContent] = useState(false);

  useEffect(() => {
    const getDirectoryList = async () => {
      try {
        const pathList = await readDir(DocumentDirectoryPath);
        setDirectory(pathList);
      } catch (error) {
        console(error);
      }
    };
    getDirectoryList();
  }, []);

  // function to handle our read file
  const handleReadFile = item => {
    setCheckContent(true);
    setReadFile(item);
  };

  // render list of files in our directory
  const renderItem = ({item}) => (
    <View>
      <TouchableOpacity
        style={styles.list}
        onPress={() => handleReadFile(item)}>
        <Text style={styles.listName}>{item.name}</Text>
      </TouchableOpacity>
    </View>
  );

  // if checkContent is true, show the ViewFile component
  if (checkContent) {
    return (
      <ViewFile content={readFIle} onclose={() => setCheckContent(false)} />
    );
  }

  return (
    <SafeAreaView style={styles.parent}>
      <View style={styles.container}>
        <Text style={styles.fileHeader}>Files</Text>
        {/* if directory length is more than 0, then map through the directory array, else show no files text */}
        {directory.length > 0 ? (
          <FlatList
            data={directory}
            renderItem={renderItem}
            keyExtractor={item => item.name}
          />
        ) : (
          <Text>No files</Text>
        )}
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  parent: {
    flex: 1,
  },
  container: {
    padding: 16,
    flex: 1,
  },
  fileHeader: {
    color: '#fff',
    fontSize: 30,
    marginBottom: 10,
    borderColor: '#ccc',
    paddingBottom: 10,
    borderBottomWidth: 1,
  },
  list: {
    marginVertical: 5,
    paddingBottom: 12,
    borderBottomWidth: 1,
    borderColor: '#ccc',
  },
  listName: {
    fontSize: 16,
  },
  button: {
    borderRadius: 5,
    marginBottom: 20,
    backgroundColor: 'green',
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    textAlign: 'center',
    paddingVertical: 10,
  },
});
export default App;

In the code above, we are getting the list of files in our directory and mapping through them using our FlatList method and our renderItem function.



Next, we click on the file or item that we want to read. On click of the item, we set our checkContent state to true. Then, using conditional rendering, we return the ViewFile component only if the **checkContent state returns true.

Moving forward, to read the contents of our file, we make use of our readFile method. First, we check if our item is a file or not using the isFile() function property that we looked at earlier. If it is a file, then using readFile, we can read its contents and display it.

Finally, we added a button that takes us back to our list page.

Downloading blob data from the cloud with react-native-fs

Now that we have seen how the react-native-fs package works and how we can use it to create and read files in our device, let us take it a step further. In this section, we will see how to download blobs like images from the cloud while checking if there is space in our local device in the process.

To check if there’s space on your device, react-native-fs provides us with a method called getFSInfo. The getFSInfo method allows us to see the device storage and the available or unused storage:

  getFSInfo().then(res => {
     console.log(res);
  });

With the above code, we can know the total free space on our device:

Log Result Showing React Native Fs Running Followed By Returned Information About Total Free Space Available On Device

Using this information about available or unused storage, we can check if the available storage is smaller or bigger than what we want to download. If it is, then the download will be allowed. Otherwise, it will be canceled and an error message will be shown to the user.

Let us put together what we have learned so far and build a simple app.

In your App.js file, copy the code below:

/* App.js */

import React, {useState, useEffect} from 'react';
import {
  SafeAreaView,
  StyleSheet,
  Text,
  FlatList,
  View,
  TouchableOpacity,
} from 'react-native';
import {
  DocumentDirectoryPath,
  readDir,
  downloadFile,
  getFSInfo,
} from 'react-native-fs';
import ViewFile from './ViewFile';
const App = () => {
  const [directory, setDirectory] = useState([]);
  const [readFIle, setReadFile] = useState(null);
  const [checkContent, setCheckContent] = useState(false);
  const [isDownloadReady, setIsDownloadReady] = useState(false);
  useEffect(() => {
    const getDirectoryList = async () => {
      try {
        const pathList = await readDir(DocumentDirectoryPath);
        setDirectory(pathList);
      } catch (error) {
        console(error);
      }
    };
    getDirectoryList();
  }, []);
  const handleReadFile = item => {
    setCheckContent(true);
    setReadFile(item);
  };
  // handle download pdf function
  const handleDownload = () => {
    const url =
      'https://upcdn.io/12a1xud/raw/uploads/2022/12/29/Chimezie%20Innocent%20Blogpost-57N1.jpg';
    const path = `${DocumentDirectoryPath}/testImage.png`;
    const response = downloadFile({
      fromUrl: url,
      toFile: path,
    });
    response.promise
      .then(async res => {
        if (res && res.statusCode === 200 && res.bytesWritten > 0) {
          console.log('size:', res.bytesWritten);
          await getFSInfo().then(response => {
            const deviceSpace = response.freeSpace * 0.001;
            if (deviceSpace > res.bytesWritten) {
              console.log('there is enough space');
              setIsDownloadReady(true);
            } else {
              alert('Not enough space');
            }
          });
        } else {
          console.log(res);
        }
      })
      .catch(error => console.log(error));
  };
  // render list of files in our directory
  const renderItem = ({item}) => (
    <View>
      <TouchableOpacity
        style={styles.list}
        onPress={() => handleReadFile(item)}>
        <Text style={styles.listName}>{item.name}</Text>
      </TouchableOpacity>
    </View>
  );
  if (checkContent) {
    return (
      <ViewFile content={readFIle} onclose={() => setCheckContent(false)} />
    );
  }
  return (
    <>
      {isDownloadReady ? (
        <SafeAreaView style={styles.parent}>
          <View style={styles.container}>
            <Text style={styles.fileHeader}>Files</Text>
            {/* if directory length is more than 0, then map through the directory array, else show no files text */}
            {directory.length > 0 ? (
              <FlatList
                data={directory}
                renderItem={renderItem}
                keyExtractor={item => item.name}
              />
            ) : null}
          </View>
        </SafeAreaView>
      ) : (
        <SafeAreaView style={styles.mainBody}>
          <View style={{alignItems: 'center'}}>
            <Text style={{fontSize: 30, textAlign: 'center'}}>
              React Native File Blob Tutorial
            </Text>
          </View>
          <TouchableOpacity
            style={styles.buttonStyle}
            activeOpacity={0.5}
            onPress={handleDownload}>
            <Text style={styles.buttonTextStyle}>Download Image</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.buttonStyle} activeOpacity={0.5}>
            <Text style={styles.buttonTextStyle}>Upload Image</Text>
          </TouchableOpacity>
        </SafeAreaView>
      )}
    </>
  );
};
const styles = StyleSheet.create({
  // same style as above
});
export default App;

After that, create a new file called ViewFile.js and copy the code below:

/* ViewFile.js */

import React from 'react';
import {
  Text,
  View,
  Image,
  StyleSheet,
  Dimensions,
  PixelRatio,
  TouchableOpacity,
} from 'react-native';
import {DocumentDirectoryPath} from 'react-native-fs';
const ViewFile = ({content, onclose}) => {
  return (
    <View style={styles.parent}>
      <View style={styles.container}>
        <View>
          <Text style={[styles.fileHeader, {textTransform: 'capitalize'}]}>
            View Image
          </Text>
        </View>
        <Image
          style={[styles.ImageContainer, {width: Dimensions.width}]}
          source={{
            uri: `file://${DocumentDirectoryPath}/${content.name}`,
          }}
        />
        <Text style={styles.content}>Name: {content?.name}</Text>
      </View>
      <TouchableOpacity style={styles.button} onPress={onclose}>
        <Text style={styles.buttonText}>Go Back</Text>
      </TouchableOpacity>
    </View>
  );
};
export default ViewFile;
const styles = StyleSheet.create({
  parent: {
    flex: 1,
  },
  container: {
    padding: 16,
    flex: 1,
  },
  fileHeader: {
    color: '#fff',
    fontSize: 30,
    marginBottom: 10,
    borderColor: '#ccc',
    paddingBottom: 10,
    borderBottomWidth: 1,
  },
  content: {
    fontSize: 18,
  },
  button: {
    backgroundColor: 'green',
    marginBottom: 20,
    marginHorizontal: 20,
    padding: 7,
    borderRadius: 5,
  },
  buttonText: {
    textAlign: 'center',
    color: '#fff',
    fontSize: 20,
  },
  ImageContainer: {
    borderRadius: 8,
    width: 250,
    height: 250,
    borderColor: 'black',
    backgroundColor: 'green',
    borderWidth: 1 / PixelRatio.get(),
    justifyContent: 'center',
    alignItems: 'center',
  },
});

Let’s break down what we are accomplishing in these code files.


More great articles from LogRocket:


We are downloading a random image into our device’s directory. Then we check if there’s enough storage space on our device — i.e., if free space is greater than the image size.

If the check returns true, we will download the image to our directory. If it returns false, then we will display an error message telling the user that there’s not enough space in our device for the download.

After the download is complete, the file system directory is displayed with the list of files we downloaded, including our image blob.

You can see the final result in the GIF below:

Phone With Dark Grey Background Showing App Title Screen Reading React Native File Blob Tutorial With Two Buttons For Downloading And Uploading Image. User Shown Tapping Download Option And Selecting Image File From List Displayed On Next Screen. Once Image File Downloads, It Is Displayed On The Next Screen Titled View Image Showing Image, File Name, And Green Button To Go Back To File List

Managing cloud data with react-native-blob-util

Now that we have seen how to create, save, read, and download blobs with react-native-fs, let us also see how we can perform the same operations with the react-native-blob-util package.

Note that this package is a fork of the now-deprecated react-native-fetch-blob package and its first fork, rn-fetch-blob. Since those packages are no longer maintained, the creator continued the project in this fork to go on supporting React Native developers in accessing and transferring data and files easily and efficiently.

Creating and saving files

To create a file with react-native-blob-util, copy the code below into the App.js file:

/* App.js */

import React, {useState} from 'react';
import {
  SafeAreaView,
  StyleSheet,
  Text,
  TextInput,
  View,
  TouchableOpacity,
  Alert,
} from 'react-native';
import RNFetchBlob from 'react-native-blob-util';
const App = () => {
  const [text, setText] = useState('');
  const docPath = RNFetchBlob.fs.dirs.DocumentDir;
  const filePath = `${docPath}/ReactNativeTutorial.txt`;

  const createFile = async () => {
    await RNFetchBlob.fs
      .writeFile(filePath, text, 'utf8')
      .then(res => Alert.alert('File created successfully'))
      .catch(error => console.log('error', e));
  };

  return (
    <SafeAreaView style={styles.parent}>
      <View style={styles.container}>
        <View style={styles.textInput}>
          <Text style={styles.title}>Enter text:</Text>
          <TextInput
            value={text}
            onChangeText={setText}
            style={styles.textArea}
            multiline
            textAlignVertical="top"
          />
        </View>
        <TouchableOpacity onPress={createFile} style={styles.button}>
          <Text style={styles.buttonText}>Create new file</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};
const styles = StyleSheet.create({
   // same style as above
});
export default App;

In the code above, we first imported the react-native-blob-util module that we installed. Next, we got the path or file directory — i.e., where we want to store our text file.

The react-native-blob-util package has an API called fs that allows us to access dirs — the directory constant. With the directory constant, we can access different folders in our phone device, such as DocumentDir, CachedDir, DownloadDir, MusicDir, PicturesDir, RingtoneDir, and so on, depending on what you are saving or reading.

In our case, we want to save a text file, so we will be using the DocumentDir folder.

Next, we created a function that will handle saving the file when we click on the “Create new file” button. Just like react-native-fs, react-native-blob-util has a writeFile method that allows us to write and save a file to the path we specified.

Assuming all our work saves correctly, we want to display a modal to the user that tells them that the operation was successful. However, if there’s an error, we want to log it in our console.

Using the readFile method

To read any file, react-native-blob-util provides a method called readFile that allows us to read the content of files in our specified directory. The syntax is as follows:

readFile(path, encoding)

Before we read the content of one of our files, let’s first get the list of files in our directory. This way, we get to see all the files we have created, all displayed in one place. We can then read each file’s content when we click on it.

To get the list of files in a directory, react-native-blob-util has a method called lstat that allows us to get the statistical data of files in a directory. The result data will be an array of objects; it also returns a promise.

With the returned objects, we can map through and display the file names. We can also accomplish other tasks, like checking the last modified date and time as well as the size of the files. See the code below to understand how this works in action:

{
    filename : 'test.pdf', // file name
    path : '/path/to/the/file/without/file/name/', // folder path
    size : 4378133, // size, in bytes
    type : 'file', // `file` or `directory`
    lastModified : 141323298 // last modified timestamp
}

With lstat and readFile methods, we can create a list of files as well as a view screen to display the content of our files. The code below demonstrates how to achieve this functionality:

/* App.js */

import React, {useState, useEffect} from 'react';
import {
  SafeAreaView,
  StyleSheet,
  Text,
  FlatList,
  View,
  TouchableOpacity,
} from 'react-native';
import RNFetchBlob from 'react-native-blob-util';

// component of the file we want to view
const ViewFile = ({content, onclose}) => {
  const [fileContent, setFileContent] = useState(null);
  useEffect(() => {
    const getContent = async () => {
      try {
        if (content.type === 'file') {
          const response = await RNFetchBlob.fs.readFile(content.path, 'utf8');
          setFileContent(response);
        }
      } catch (error) {
        console.log(error);
      }
    };
    getContent();
    return () => getContent();
  }, []);
  return (
    <View style={styles.parent}>
      <View style={styles.container}>
        <View>
          <Text style={[styles.fileHeader, {textTransform: 'capitalize'}]}>
            {content.filename.replace('.txt', '')}
          </Text>
        </View>
        <Text style={styles.content}>{fileContent}</Text>
      </View>
      <TouchableOpacity style={styles.button} onPress={onclose}>
        <Text style={styles.buttonText}>Go Back</Text>
      </TouchableOpacity>
    </View>
  );
};

// main component
const App = () => {
  const [directory, setDirectory] = useState([]);
  const [readFIle, setReadFile] = useState(null);
  const [checkContent, setCheckContent] = useState(false);
  useEffect(() => {
    const docPath = RNFetchBlob.fs.dirs.DocumentDir;
    const getDirectoryList = async () => {
      await RNFetchBlob.fs
        .lstat(docPath)
        .then(response => {
          console.log(response);
          setDirectory(response);
        })
        .catch(error => console.error(error));
    };
    getDirectoryList();
  }, []);
  // function to handle our read file
  const handleReadFile = item => {
    setCheckContent(true);
    setReadFile(item);
  };

  // render list of files in our directory
  const renderItem = ({item}) => (
    <View>
      <TouchableOpacity
        style={styles.list}
        onPress={() => handleReadFile(item)}>
        <Text style={styles.listName}>{item.filename}</Text>
      </TouchableOpacity>
    </View>
  );
  // if checkContent is true, show the ViewFile component
  if (checkContent) {
    return (
      <ViewFile content={readFIle} onclose={() => setCheckContent(false)} />
    );
  }
  return (
    <SafeAreaView style={styles.parent}>
      <View style={styles.container}>
        <Text style={styles.fileHeader}>Files</Text>
        {/* if directory length is more than 0, then map through the directory array, else show no files text */}
        {directory.length > 0 ? (
          <FlatList
            data={directory}
            renderItem={renderItem}
            keyExtractor={item => item.name}
          />
        ) : (
          <Text>No files</Text>
        )}
      </View>
    </SafeAreaView>
  );
};
const styles = StyleSheet.create({
   // same style as above
});
export default App;

Uploading a blob to the cloud with react-native-blob-util

The react-native-blob-util package has an API called fetch that allows us to perform operations like uploading and downloading blobs to the cloud. It uses the native Fetch API that allows PUT, POST, GET, and PATCH methods.

In the code below, you can see that we are wrapping the file we want to upload using an API called wrap that the react-native-blob-util package provides:

  RNFetchBlob.fetch(
    'POST',
    'cloud-storage-url',
    {
      Authorization: 'Bearer access-token...',
      'Content-Type': 'multipart/form-data',
    },
    RNFetchBlob.wrap('path-to-the-file'),
  )
    .then(res => {
      console.log(res);
    })
    .catch(error => {
      console.log(error);
    });

Downloading a blob from the cloud with react-native-blob-util

To complete this section and conclude the article, let us see how to download blobs like images from the cloud using the react-native-blob-util package.

Note that for downloading blobs, we are using the react-native-blob-util Download Manager. This allows us to provide a better user experience by showing the user the download progress of the blob, along with when the blob is successfully downloaded.

To do this, we set useDownloadManager and notifications to true in our config object:

RNFetchBlob.config({
      path: path,
      fileCache: true,
      addAndroidDownloads: {
        useDownloadManager: true,
        notification: true,
        title: 'Download Successful! Click to view',
        description: 'An image file.',
        mime: 'image/png',
      },
    })

We can set the title of the success notification to display whatever we want to the user, as well as setting a blob description — i.e., whether it is an image, music, or movie file. The path is the file directory where we want to save the downloaded file.

Let’s look at the complete code example below, which is still using the fetch API:

/* App.js */

import React from 'react';
import {
  TouchableOpacity,
  SafeAreaView,
  StyleSheet,
  Text,
  View,
} from 'react-native';
import RNFetchBlob from 'react-native-blob-util';

const App = () => {
  const docPath = RNFetchBlob.fs.dirs.DocumentDir;

  // handle download image function
  const handleDownload = async () => {
    const url =
      'https://upcdn.io/12a1xud/raw/uploads/2022/12/29/Chimezie%20Innocent%20Blogpost-57N1.jpg';
    const path = `${docPath}/DownloadImage.png`;
    await RNFetchBlob.config({
      path: path,
      fileCache: true,
      addAndroidDownloads: {
        useDownloadManager: true,
        notification: true,
        title: 'Download Successful! Click to view',
        description: 'An image file.',
        mime: 'image/png',
      },
    })
      .fetch('GET', url)
      .then(async res => {
        if (res && res.info().status === 200) {
          console.log(res);
        } else {
          console.log(res);
        }
      })
      .catch(error => console.log(error));
  };
  return (
    <SafeAreaView style={styles.mainBody}>
      <View style={{alignItems: 'center'}}>
        <Text style={{fontSize: 30, textAlign: 'center'}}>
          React Native Blob Util Tutorial
        </Text>
      </View>
      <TouchableOpacity
        style={styles.buttonStyle}
        activeOpacity={0.5}
        onPress={handleDownload}>
        <Text style={styles.buttonTextStyle}>Download Image</Text>
      </TouchableOpacity>
      <TouchableOpacity style={styles.buttonStyle} activeOpacity={0.5}>
        <Text style={styles.buttonTextStyle}>Upload Image</Text>
      </TouchableOpacity>
    </SafeAreaView>
  );
};
const styles = StyleSheet.create({
  mainBody: {
    flex: 1,
    justifyContent: 'center',
    padding: 20,
  },
  buttonStyle: {
    backgroundColor: '#307ecc',
    borderWidth: 0,
    color: '#FFFFFF',
    borderColor: '#307ecc',
    height: 40,
    alignItems: 'center',
    borderRadius: 30,
    marginLeft: 35,
    marginRight: 35,
    marginTop: 15,
  },
  buttonTextStyle: {
    color: '#FFFFFF',
    paddingVertical: 10,
    fontSize: 16,
  },
});
export default App;

Finally, this is what our app looks like when downloading a sample image from the cloud using react-native-blob-util:

Phone With Dark Grey Background Showing App Title Screen Reading React Native Blob Util Tutorial With Two Buttons For Downloading And Uploading Image. User Shown Tapping Download Option And Selecting Image File From Download Manager Shown On Next Screen. Once Image File Downloads, User Is Shown Options For Displaying Image. After Selecting Gallery Option, Image Is Displayed Full Size With Black Background

Conclusion

The react-native-fs and react-native-blob-util packages allow us to access the file systems of our devices and perform certain operations, such as the ones demonstrated in this article.

We explored some things we can accomplish with these packages, like creating, saving, and reading files. Additionally, we saw how we can fetch and manage blobs in React Native, including uploading and downloading blobs from the cloud. During this process, we can perform a device storage check to provide better user experiences.

If you followed along with this tutorial and practiced the demonstrated examples, you should find it easy to fetch and handle blob data in React Native with react-native-fs and react-native-blob-util on your own. Make sure to comment with any questions you have while applying this knowledge to your projects.

LogRocket: Instantly recreate issues in your React Native apps.

LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.

LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.

Start proactively monitoring your React Native apps — .

Chimezie Innocent I am Chimezie, a software developer based in Nigeria. I am highly skilled in HTML, CSS, and JS to build web-accessible and progressive apps. I'm also skilled with React for web, React Native for Android apps, and Tailwind CSS. I write technical articles, too.

2 Replies to “How to fetch and handle blob data in React…”

Leave a Reply