логотип PurpleSchool
логотип PurpleSchool

Гайд по файловой системе в React Native

Автор

Олег Марков

Введение

Файловая система — это ключевой компонент любого мобильного приложения, который позволяет работать с файлами: сохранять фотографии, хранить логи, создавать документы, кэшировать данные и даже организовывать офлайн-работу. В React Native работа с файлами слегка отличается от привычной работы в JavaScript в браузере или Node.js, поскольку на мобильных платформах (Android и iOS) действуют свои ограничения и особенности организации хранения данных.

В этой статье я подробно расскажу, как работать с файловой системой в React Native. На практических примерах вы узнаете, как записывать, читать, удалять файлы и директории, получать список файлов, вычислять хэш и многое другое. Здесь собрана вся основная информация, необходимая как начинающим, так и опытным мобильным разработчикам.

Обзор работы с файловой системой в React Native

По умолчанию React Native не предоставляет встроенных средств для работы с локальной файловой системой. Для этих целей наиболее популярен пакет react-native-fs. Он кроссплатформенный и поддерживает все ключевые операции с файлами для Android и iOS.

Для определённых кейсов применяются также библиотеки expo-file-system, rn-fetch-blob, но в большинстве случаев современного приложения хватает возможностей react-native-fs.

Работа с файловой системой в React Native позволяет сохранять и загружать данные, работать с изображениями и другими ресурсами. Важно понимать, как получить доступ к различным директориям, читать и записывать файлы, а также обрабатывать ошибки и обеспечивать безопасность данных. Для более глубокой работы с файлами может потребоваться понимание работы с нативными модулями. Если вы хотите детальнее погрузиться в работу с файловой системой и другими нативными возможностями в React Native, — приходите на наш большой курс React Native и Expo Router. На курсе 184 уроков и 11 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Установка и базовая настройка

Давайте начнем с установки:

npm install react-native-fs
# или
yarn add react-native-fs

После этого следуйте инструкции по установке Native-кода (особенно важно для старых версий React Native):

  • Для Android убедитесь, что package автоматически линкован или пропишите его вручную в android/settings.gradle и android/app/build.gradle (актуально для React Native до 0.60).
  • Для iOS выполните cd ios && pod install.

Теперь библиотека готова к работе, и вы можете импортировать её в своих файлах:

import RNFS from 'react-native-fs'

Основные директории и работа с путями

Перед тем, как приступить к чтению и записи, важно понять, где можно хранить файлы.

Основные стандартные директории

В мобильных ОС системой определено несколько папок для работы:

  • DocumentDirectoryPath — директория для документов пользователя, разрешена синхронизация с iCloud.
  • ExternalDirectoryPath (только Android) — внешний storage, видно пользователю.
  • CachesDirectoryPath — папка для кэшированных данных, может быть очищена ОС.
  • TemporaryDirectoryPath (iOS) — временные файлы.

Смотрите, как обратиться к этим папкам:

// Получаем путь к директории документов
const documentsPath = RNFS.DocumentDirectoryPath

// Путь к кэшу
const cachePath = RNFS.CachesDirectoryPath

// Для Android — внешний сторидж
const externalPath = RNFS.ExternalDirectoryPath

Полученные пути — обычные строки, их можно объединять с помощью / или использовать специальные утилиты.

Пример построения пути к новому файлу

const myFilePath = `${RNFS.DocumentDirectoryPath}/myData.txt`
// Файл будет создан в директории документов

Чтение и запись файлов

Как записывать данные в файл

Запись данных предельно проста. Вот рабочий пример:

const filePath = `${RNFS.DocumentDirectoryPath}/hello.txt`

// Запишем строку Hello, world!
RNFS.writeFile(filePath, 'Hello, world!', 'utf8')
  .then(() => {
    // Запись прошла успешно
    console.log('Файл создан!')
  })
  .catch(error => {
    // При ошибке выводим ее в консоль
    console.error('Ошибка записи файла:', error)
  })

Вы всегда должны указывать кодировку — чаще всего используют utf8.

Если файл уже существует, то функция перезапишет его полностью.

Чтение данных из файла

Прочитать данные можно так:

RNFS.readFile(filePath, 'utf8')
  .then(contents => {
    // В contents — строка из файла
    console.log('Содержимое файла:', contents)
  })
  .catch(error => {
    // Например, если файл не найден
    console.error('Ошибка чтения файла:', error)
  })

Если файл содержит бинарные данные — не забудьте поменять кодировку, например на base64.

Работа с JSON

Очень удобно хранить сериализованные данные:

// Сохраним объект
const data = { loggedIn: true, name: 'Anna' }
await RNFS.writeFile(filePath, JSON.stringify(data), 'utf8')

// И потом прочитаем
const json = await RNFS.readFile(filePath, 'utf8')
const parsed = JSON.parse(json)
// parsed: { loggedIn: true, name: 'Anna' }

Используйте try-catch для ловли ошибок парсинга.

Работа с директориями

Проверка существования файлов и папок

Чтобы проверить, существует ли определённый файл или папка, используйте метод exists:

const fileExists = await RNFS.exists(filePath)
if (fileExists) {
  console.log('Файл есть')
} else {
  console.log('Файла нет')
}

Создание и удаление директорий

Создать новую папку можно так:

await RNFS.mkdir(`${RNFS.DocumentDirectoryPath}/myFolder`)

Удалить папку (вместе с содержимым!) или файл — с помощью unlink:

await RNFS.unlink(`${RNFS.DocumentDirectoryPath}/myFolder`)
// Будьте внимательны — папка удалится вместе со всеми файлами

Получение списка файлов в папке

Для просмотра содержимого директории:

const items = await RNFS.readDir(RNFS.DocumentDirectoryPath)
items.forEach(item => {
  // Выводим путь к каждому элементу
  console.log(item.path)
  // item.isFile(), item.isDirectory() — позволяют узнать тип
})

Работа с бинарными файлами (картинки, аудио и проч.)

Многим разработчикам нужно сохранять не только текстовые данные, но и, например, фотографии пользователя или аудиозаписи.

Запись и чтение файлов в base64

Вам поможет работа с кодировкой base64. Смотрите пример:

// Пример сохранения картинки в base64
await RNFS.writeFile(filePath, base64String, 'base64')

// Чтение картинки
const data = await RNFS.readFile(filePath, 'base64')
// Получили строку base64 для дальнейшего использования

Копирование и перемещение файлов

Иногда нужно скопировать или переместить файл из одной директории в другую. Для этого есть методы copyFile и moveFile.

// Копирование файла
await RNFS.copyFile(srcPath, destPath)

// Перемещение файла
await RNFS.moveFile(oldPath, newPath)

Оба метода не создают новые папки, если они отсутствуют — их нужно создать заранее!

Загрузка файлов из интернета

Для загрузки файлов используйте метод downloadFile. Вот рабочий пример:

const destPath = `${RNFS.DocumentDirectoryPath}/image.jpg`

const options = {
  fromUrl: 'https://example.com/image.jpg', // cсылка на файл
  toFile: destPath, // куда сохранять
  background: true, // выполнять в фоне
  progress: res => {
    const percent = (res.bytesWritten / res.contentLength) * 100
    console.log(`Загрузка: ${percent}%`)
  }
}

const download = RNFS.downloadFile(options)
const result = await download.promise

if (result.statusCode === 200) {
  console.log('Файл загружен!')
}

В случае ошибок promise завершится с ошибкой, которую нужно обработать через try-catch.

Особенности работы на Android и iOS

Пермишены и доступ к файлам

Android

С Android 6.0 и выше критически важно запрашивать разрешение на доступ к файловой системе у пользователя. Для этого используйте пакет @react-native-community/permissions:

import { PermissionsAndroid } from 'react-native'

async function requestStoragePermission() {
  try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
    )
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      console.log('Доступ есть')
    } else {
      console.log('Доступ запрещен')
    }
  } catch (err) {
    console.warn(err)
  }
}

Чтобы работать во "внешней" директории (ExternalDirectoryPath), обязательно запрашивайте разрешения и пропишите их в AndroidManifest.xml.

iOS

На iOS приложение всегда работает только в своем "песочнице", и доступ к файловой системе за её пределами получить нельзя. То есть файл, созданный приложением — доступен только ему.

Ограничения и тонкости платформ

  • Android: В новых версиях (Android 11+) ужесточились правила доступа к файлам — используйте специально предназначенные директории (например, DocumentDirectoryPath).
  • iOS: Не используйте для хранения пользовательских данных временные каталоги (TemporaryDirectoryPath), т.к. iOS их может удалить в любой момент.

Прочие полезные методы

Получение информации о файле

Вы можете узнать размер, дату или другие сведения:

const stat = await RNFS.stat(filePath)
console.log(stat.size) // Размер файла в байтах
console.log(stat.mtime) // Дата последней модификации
console.log(stat.isFile()) // true если файл, false если папка
console.log(stat.isDirectory())

Вычисление хэша файла

Если требуется уникально идентифицировать файл или сравнить его содержимое:

const hash = await RNFS.hash(filePath, 'md5')
console.log(`MD5 хэш файла: ${hash}`)

Пример: сохранение и отображение картинки

Давайте рассмотрим распространённый кейс — пользователь выбирает фото, оно сохраняется в файловой системе и затем отображается в приложении.

Пояснения будут даны пошагово

  1. Сохраняем base64-строку как файл:
const filePath = `${RNFS.DocumentDirectoryPath}/myImage.jpg`
await RNFS.writeFile(filePath, base64String, 'base64')
  1. Открываем файл через компонент Image:
import { Image } from 'react-native'

<Image
  source={{ uri: `file://${filePath}` }} // file:// обязателен!
  style={{ width: 100, height: 100 }}
/>

file:// — важная часть пути, иначе изображение может не загрузиться!

  1. Для удаления фото используйте:
await RNFS.unlink(filePath)

Безопасность и большие файлы

Обработка больших файлов требует осторожности — не читайте их в оперативную память целиком, используйте методы потоковой работы (read() с указанием количества байт, если критично). Всегда валидируйте пользовательские данные перед сохранением.

Храните sensitive-данные только в директории приложения, защищённой ОС, и не отдавайте доступ сторонним приложениям.

Заключение

Работа с файловой системой в React Native становится максимально удобной при использовании проверенных библиотек, таких как react-native-fs. С их помощью вы сможете реализовать все основные сценарии по хранению, чтению, удалению и загрузке файлов. В статье были разобраны ключевые методы, особенности работы с директориями, текстовыми и бинарными файлами, вопросы безопасности и платформенные нюансы.

Вы можете смело использовать эти знания для создания офлайн-режимов в приложении, работы с фото/видео, кэширования данных, хранения конфиденциальной информации и интеграции с сервисами на устройствах пользователей.

Работа с файловой системой - это важный аспект разработки, но не стоит забывать и о других важных вещах, как управление состоянием и создание навигации. На нашем курсе React Native и Expo Router вы найдете все необходимые знания для освоения React Native разработки. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир React Native прямо сегодня.

Частозадаваемые технические вопросы

Как очистить все файлы из определённой папки?

— Получите список файлов через readDir, затем для каждого файла вызовите unlink. Пример: javascript const files = await RNFS.readDir(folderPath) for (const file of files) { await RNFS.unlink(file.path) }

Почему файлы пропадают после обновления приложения (Android)?

— Если файлы хранились во временных или кэширующих директориях, система могла их очистить. Используйте DocumentDirectoryPath или ExternalDirectoryPath для долгосрочного хранения.

Как ограничить размер кэшируемых файлов?

— После каждой записи файла проверяйте общий размер через сумму свойств size всех файлов в директории. Если превышаете лимит, удаляйте самые старые с помощью сортировки по mtime.

Как работать с файлами PDF?

— Для работы с PDF-файлами используйте те же методы для сохранения и чтения, а для отображения используйте компоненты типа react-native-pdf, передавая в source путь к файлу ({ uri: 'file://' + filePath }).

Как защитить файлы от чтения другими приложениями?

— На Android храните важные файлы во внутренней директории приложения (DocumentDirectoryPath). На iOS все файлы по умолчанию доступны только вашему приложению благодаря "песочнице".

Стрелочка влевоОтображение списков данных в React NativeИнтеграция камеры в приложение на React NativeСтрелочка вправо

Постройте личный план изучения React-native до уровня Middle — бесплатно!

React-native — часть карты развития Mobile

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по React-native

Работа со ScrollView в React NativeРабота с видео в React NativeКак реализовать аудиоплеер на React NativeНастройка и использование input и textinput в React NativeИнтеграция видео плеера в приложение на React NativeИспользование выпадающих списков в React NativeСоздание и настройка native module на React NativeКак создать модальные окна в React NativeРабота с изображениями в React NativeОтображение списков данных в React NativeГайд по файловой системе в React NativeИнтеграция камеры в приложение на React NativeСоздание интерактивных кнопок в React Native
Как использовать векторные иконки в React Native5 популярных библиотек UI компонентов React NativeСоздание и использование tabs в React NativeРуководство по стилизации компонентов в React NativeОптимизация переходов между экранами в React NativeАдаптация safe area context на React NativeОбзор библиотек для навигации в React NativeСоздание сложных анимаций (reanimated) на React NativeИспользование библиотеки стилей Paper в React NativeРуководство по navigation в React NativeОптимизация отображения списков в React NativeКак реализовать linking на React NativeГайд по UI-китам для React NativeГде искать elements для приложения на React NativeРабота с цветами в React Native
Открыть базу знаний

Лучшие курсы по теме

изображение курса

React Native и Expo Router

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Основы JavaScript

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий