Reaction-native-fs: Как читать локальные изображения (Получить base64 локального файла)

В моем приложении есть локальные файлы, которые я читаю так:

<Image source={require("../../img/pic1.jpg") />

Как читать этот файл, используя RNFS.readFile(filepath, "base64");с помощью RNFS.readFile("../../img/pic1.jpg", "base64"); выдает ошибку "нет такого файла"

4 ответа

Решение

react-native-fs будет иметь доступ только к файлам из хранилища устройства. Так что эта проблема ставит в тупик. Эти файлы связаны во время сборки, так как мы можем получить к ним доступ в процессе разработки или производства?

Структура моего проекта

├── android
├── app
│   └── assets
│       └── images
└── ios

Я храню свои изображения внутри ./app/assets/images/

развитие

В процессе разработки или отладки файлы передаются на устройство через Metro-пакет, поэтому они не сохраняются на устройстве. Таким образом, доступ к ним из хранилища устройств будет невозможен. Вы должны были бы предоставить какую-то смоделированную функциональность для разработки. Можно использовать __DEV__ разрешить запуск различных функций в зависимости от среды https://facebook.github.io/react-native/docs/javascript-environment

if (__DEV__) {
  // do something in development
} else {
  // do something in production
}

производство

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

IOS

Я обнаружил, что файлы находятся в папке с именем assets которые находятся в MainBundlePath,

Так что если вы хотите получить доступ к следующему файлу в моем локальном каталоге ./app/assets/images/image.png вам понадобится следующий путь к файлу: RNFS.MainBundlePath + /assets/app/assets/images/image.png чтобы получить доступ к нему на устройстве.

Вы можете проверить, чтобы увидеть путь к файлу, посмотрев на Packaging.log что генерируется с вашим ipa,

Android

Android не имеет папки с именем MainBundlePath это только на iOS, Я провел некоторое время, исследуя и просматривая различные папки на устройстве, но не смог получить доступ к изображениям, которые в комплекте. Казалось бы, они не доступны так, как мы надеемся, используя react-native-fs,

Возможные решения

rn-fetch-blob

rn-fetch-blob имеет функциональность для обоих ios а также Android читать из каталога ресурсов

Чтобы получить доступ к файлам для iOS вы бы сделали что-то вроде этого:

RNFetchBlob.fs.stat(fs.dirs.MainBundleDir + '/whatever/files/you/added.mp3').then( stats => {...});

И для Android вы бы сделали что-то вроде этого:

RNFetchBlob.fs.stat(fs.asset('/whatever/files/you/added.mp3').then( stats => {...});

Это дает предупреждение о сжатии активов Gradle.

Gradle будет сжимать связанные активы по умолчанию. Для взаимодействия с файлами ресурсов с этим модулем сжатие должно быть отключено. Пожалуйста, смотрите Как получить доступ к файлам из ресурсов для более подробной информации.

Это может объяснить, почему я не смог найти какие-либо активы в Android при просмотре с помощью react-native-fs

Вы можете прочитать больше об использовании rn-fetch-blob и его файловая система здесь https://github.com/joltup/rn-fetch-blob

Хранение файлов в нативных проектах

Вместо того, чтобы полагаться на упаковщик, чтобы упаковать изображения для вас и поместить их на устройство. Вы можете хранить их копии уже в iOS а также Android проекты. Это дает преимущество в том, что изображения будут доступны в процессе разработки, однако вы сохраняете изображения несколько раз, и это может привести к увеличению размеров приложения.

Хранение изображений как base64

Вы можете хранить изображения в виде строк base64 в файлах json, а затем запрашивать их в своем приложении. Это будет означать, что они будут уже в base64 (поэтому приложение не должно выполнять никаких преобразований), но вы снова увеличите размер своего приложения. Если это только небольшое количество изображений, это может быть самый простой вариант.

Обновление 2021 года для использования RNFS

iOS

Предложение Эндрю по использованию RNFS.MainBundlePath по-прежнему отлично работает.

Android

RNFS может читать файлы в каталоге ресурсов приложения с помощью:

RNFS.readFileAssets(filepath:string, encoding?: string)

Кодировка может быть одной из utf8 (по умолчанию), ascii или base64. Используйте base64 для чтения двоичных файлов. filepath - относительный путь к файлу от корня папки ресурсов.

Пример, если ваш файл находится непосредственно в каталоге ваших ресурсов:

RNFS.readFileAssets('coolimage.png', 'base64');

https://github.com/itinance/react-native-fs#readfileassetsfilepathstring-encoding-string-promisestring

Преобразование в Base64 работает

       const DownloadUrl = async () => {
var RNFS = require("react-native-fs");

RNFS.downloadFile({
  fromUrl: "https://facebook.github.io/react-native/img/header_logo.png",
  toFile: `${RNFS.DocumentDirectoryPath}/react-native.png`,
}).promise.then(async (response: string) => {
  RNFS.readFile(
    `${RNFS.DocumentDirectoryPath}/react-native.png`,
    "base64"
  ).then((base64String: any) => {
    console.log(
      "base64String===>",
      `${RNFS.DocumentDirectoryPath}/react-native.png`,
      base64String
    );
  });
  console.log("response ====>", RNFS.DocumentDirectoryPath, response);
});

};

Просто используя filename = response.uri.replace ('file:', '')

Финальный код:

if (Platform.OS === 'ios') {
      filename = response.uri.replace('file:', '')
} else {
      filename = response.uri
}

Работаю сейчас...

Другие вопросы по тегам