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');
Преобразование в 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
}
Работаю сейчас...