在React Native中将文件和图像上传到Firebase Cloud Storage

在React Native中将文件和图像上传到Firebase Cloud Storage

这是我们的第三篇文章 反应原生 Firebase 系列,在这个例子中我们将看到什么是Firebase Cloud Storage? 以及如何将云存储集成到React Native App中? 在此示例中,我们将了解如何使用 React Native Too 在云存储上上传文件或图像、列出已上传的文件以及共享/打开已上传的文件。

让我们从 Firebase 云存储示例开始。

推荐:手工艺术家和工匠WooCommerce主题Zass主题

Firebase 云存储

存储是为需要存储和提供用户生成的内容(例如照片或视频)的应用程序开发人员而构建的。 它类似于AWS S3,可用于存储文件和其他内容。

如果您使用 Firebase Cloud Storage,那么您的数据将存储在 Google Cloud Storage 存储桶上,这是一种具有高可用性和全局冗余的 EB 级对象存储解决方案。 Firebase 存储的集成非常简单,一旦将其集成到应用程序中,您就可以安全地将任何文件直接从移动设备上传到 Cloud Fire 存储

Firebase Cloud Storage 存储桶以分层结构呈现,就像文件系统一样。 通过创建对文件的引用,您的应用程序可以访问它。 然后,这些引用可用于上传或下载数据、获取或更新元数据或删除文件。 引用可以指向特定文件或层次结构中的更高级别节点。

存储模块还提供对多个存储桶的支持。 云存储的一个常见用例是将其用作图像的全球内容分发网络 (CDN)。

创建参考并上传/下载

要在 Firebase Cloud Storage 上上传任何文件或图像,您需要导入存储

import storage from '@react-native-firebase/storage';

并且必须创建一个参考,A 参考 是指向存储桶上某个文件的本地指针。 该文件可以是已存在的文件,也可以是尚不存在的文件。 要创建引用,请使用 ref 方法

const reference = storage().ref('my-file.txt');

您还可以指定位于深层嵌套目录中的文件:

const reference = storage().ref('/myfiles/mycollection/my-file.txt');

要直接从用户设备上传文件, 放置文件 引用上的方法接受用户设备上文件的字符串路径。

const task = reference.putFile(localFilePath);

putFile 方法返回一个任务,如果需要,它允许您挂钩当前上传进度等信息:

const task = reference.putFile(pathToFile);
task.on('state_changed', taskSnapshot => {
  console.log(`${taskSnapshot.bytesTransferred} transferred 
  out of ${taskSnapshot.totalBytes}`);
});
task.then(() => {
  console.log('Image uploaded to the bucket!');
});

任务还提供暂​​停和恢复正在进行的操作的能力

task.pause();
task.resume();

将文件上传到存储桶时,它们不会自动通过 HTTP URL 供使用。 要生成新的下载 URL,您需要调用 获取下载地址 方法参考:

const url = await storage()
  .ref('images/profile-1.png')
  .getDownloadURL();

如果您希望查看特定存储桶引用中当前文件和目录的完整列表,您可以使用 列表 方法。

reference.list().then((result) => {
    setListData(result.items);
});

示例说明

在此示例中,我们将创建一个主屏幕,其中包含多个选项以导航到任何屏幕。 我们将有一个屏幕,它将帮助我们选择一个文件并上传所选文件。 我们还将创建一个屏幕来列出任何存储桶中的文件。 让我们看看它的设置和代码。

制作 React Native 应用程序

React Native 入门将帮助您更多地了解如何制作 React Native 项目。 我们将使用 React Native 命令行界面来制作我们的 React Native 应用程序。

如果您之前安装了全局的react-native-cli软件包,请将其删除,因为它可能会导致意外问题:

npm uninstall -g react-native-cli @react-native-community/cli

运行以下命令创建一个新的 React Native 项目

npx react-native init ProjectName

如果你想使用特定的 React Native 版本启动一个新项目,你可以使用 –version 参数:

npx react-native init ProjectName --version X.XX.X

注意如果上述命令失败,您可能使用的是旧版本 react-native 或者 react-native-cli 在您的电脑上全局安装。 尝试卸载 cli 并使用 npx 运行 cli。

这将在项目目录中创建一个带有名为 App.js 的索引文件的项目结构。

Firebase SDK 集成

要从任何 React Native Firebase 示例开始,您需要将 Firebase 集成到您的应用程序中,我专门为此详细制作了一篇单独的文章,您将在其中看到在 Android 版 React Native 应用程序中添加 Firebase 的点对点过程,以及iOS 两者都有。

请访问如何在 Android 和 iOS 应用程序中集成 Firebase,然后返回执行下一步。

完成 Firebase 集成后,您可以安装更多依赖项。

安装依赖项

要安装依赖项,请打开终端并使用以下命令跳转到您的项目

cd ProjectName

对于 React Native Firebase,我们需要安装和设置应用程序模块

npm install @react-native-firebase/app --save

现在安装存储模块

npm install @react-native-firebase/storage --save

接下来,我们将使用文档选择器来选择要上传到 Firebase Cloud Storage 的文件,要使用文档选择器安装以下依赖项

npm install react-native-document-picker --save

这对于云存储来说已经足够了,但在这个示例中,我们还将使用 React Navigation,因为我们将切换屏幕,因此还要安装以下 React-navigation 依赖项

npm install @react-navigation/native --save

其他用于反应导航的支持库

npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view --save
npm install @react-navigation/stack --save

此命令会将所有依赖项复制到您的 node_module 目录中。 –save 是可选的,它只是更新 package.json 文件中的依赖项。

CocoaPods 安装

React Native 0.60 更新后,他们引入了自动链接,因此我们不需要链接库,但对于 iOS,我们需要安装 pod。 因此要安装 pod,请使用

cd ios/ && pod install --repo-update && cd ..

创建默认存储桶

  • 从导航窗格中 Firebase 控制台,选择存储,然后单击开始。
  • 查看有关使用安全规则保护存储数据的消息。 在开发过程中,考虑 设置公共访问规则
  • 选择一个 地点 对于您的默认存储桶。
    • 此位置设置是您项目的默认 Google Cloud Platform (GCP) 资源位置。 请注意,此位置将用于项目中需要位置设置的 GCP 服务,特别是您的 Cloud Firestore 数据库和 App Engine 应用(如果您使用 Cloud Scheduler,则需要)。
    • 如果您无法选择位置,则您的项目已有默认 GCP 资源位置。 它是在项目创建期间或设置另一个需要位置设置的服务时设置的。
    • 如果您使用 Blaze 计划,则可以创建多个存储桶,每个存储桶都有自己的位置。
    • 警告:设置项目的默认 GCP 资源位置后,您将无法更改它。
  • 单击“完成”。

设置公共访问

Cloud Storage for Firebase 提供了一种声明性规则语言,可让您定义数据的结构方式、索引方式以及数据的读取和写入时间。 默认情况下,对存储的读写访问受到限制,因此只有经过身份验证的用户才能读取或写入数据。 无需设置即可开始使用 验证, 你可以 配置公共访问规则

这确实使存储向任何人开放,甚至是不使用您的应用程序的人,因此请务必在设置身份验证时再次限制您的存储。

对于此示例,我们将设置公共访问权限并将其打开 贮存 控制台中的选项,单击 规则,用以下规则更新并且 发布

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth == null; 
    }
  }
}

react_native_firebase_cloud_storage_security_rules

React Native 云存储的项目结构

请创建以下项目结构并复制下面给出的代码。

React_native_firebase_cloud_storage_file_struct.png

你可以看到

  1. 应用程序.js 包含主要导航
  2. 主屏.js,将有不同的选项来打开不同的屏幕
  3. 文件列表屏幕.js列出云存储中的所有文件
  4. 上传文件屏幕.js选择并上传云存储上的文件

在 React Native 中集成云存储的代码

请在任何代码编辑器中打开 App.js 并将代码替换为以下代码

应用程序.js

// #3 Uploading Files and Images to Firebase Cloud Storage in React Native
// https://aboutreact.com/react-native-firebase-cloud-storage/

import "react-native-gesture-handler";

import * as React from "react";

import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";

import HomeScreen from "./pages/HomeScreen";
import UploadFileScreen from "./pages/UploadFileScreen";
import FilesListingScreen from "./pages/FilesListingScreen";

const Stack = createStackNavigator();

const App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="HomeScreen"
        screenOptions={{
          headerStyle: {
            backgroundColor: "orange", //Set Header color
          },
          headerTintColor: "#fff", //Set Header text color
          headerTitleStyle: {
            fontWeight: "bold", //Set Header text style
          },
        }}
      >
        <Stack.Screen
          name="HomeScreen"
          component={HomeScreen}
          options={{ title: "Home" }}
        />
        <Stack.Screen
          name="UploadFileScreen"
          component={UploadFileScreen}
          options={{ title: "Upload File" }}
        />
        <Stack.Screen
          name="FilesListingScreen"
          component={FilesListingScreen}
          options={{ title: "Uploaded Files" }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default App;

页面/HomeScreen.js

// #3 Uploading Files and Images to Firebase Cloud Storage in React Native
// https://aboutreact.com/react-native-firebase-cloud-storage/

// Import React in our code
import React from "react";

// Import all the components we are going to use
import {
  SafeAreaView,
  StyleSheet,
  View,
  Text,
  TouchableOpacity,
} from "react-native";

const HomeScreen = (props) => {
  return (
    <SafeAreaView style={(style = styles.container)}>
      <View style={styles.innerContainer}>
        <Text style={styles.titleText}>
          Uploading Files and Images to Firebase Cloud
          Storage in React Native
        </Text>
        <TouchableOpacity
          style={styles.buttonStyle}
          onPress={() =>
            props.navigation.navigate("UploadFileScreen")
          }
        >
          <Text style={styles.buttonTextStyle}>
            Upload File
          </Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={styles.buttonStyle}
          onPress={() =>
            props.navigation.navigate("FilesListingScreen")
          }
        >
          <Text style={styles.buttonTextStyle}>
            Uploaded File Listing
          </Text>
        </TouchableOpacity>
      </View>
      <Text style={styles.footerHeading}>
        React Native Firebase Cloud Storage
      </Text>
      <Text style={styles.footerText}>
        www.aboutreact.com
      </Text>
    </SafeAreaView>
  );
};

export default HomeScreen;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
  },
  innerContainer: {
    flex: 1,
    alignItems: "center",
    padding: 35,
  },
  titleText: {
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
    padding: 20,
  },
  buttonTextStyle: {
    color: "white",
    fontWeight: "bold",
  },
  buttonStyle: {
    alignItems: "center",
    backgroundColor: "orange",
    padding: 10,
    width: "100%",
    marginTop: 16,
  },
  footerHeading: {
    fontSize: 18,
    textAlign: "center",
    color: "grey",
  },
  footerText: {
    fontSize: 16,
    textAlign: "center",
    color: "grey",
  },
});

页面/UploadFileScreen.js

// #3 Uploading Files and Images to Firebase Cloud Storage in React Native
// https://aboutreact.com/react-native-firebase-cloud-storage/

// Import React in our code
import React, { useState } from "react";

// Import all the components we are going to use
import {
  SafeAreaView,
  StyleSheet,
  Text,
  View,
  ActivityIndicator,
  TouchableOpacity,
} from "react-native";

// Firebase Storage to upload file
import storage from "@react-native-firebase/storage";
// To pick the file from local file system
import DocumentPicker from "react-native-document-picker";

const UploadFileScreen = () => {
  // State Defination
  const (loading, setLoading) = useState(false);
  const (filePath, setFilePath) = useState({});
  const (process, setProcess) = useState("");

  const _chooseFile = async () => {
    // Opening Document Picker to select one file
    try {
      const fileDetails = await DocumentPicker.pick({
        // Provide which type of file you want user to pick
        type: (DocumentPicker.types.allFiles),
      });
      console.log(
        "fileDetails : " + JSON.stringify(fileDetails)
      );
      // Setting the state for selected File
      setFilePath(fileDetails);
    } catch (error) {
      setFilePath({});
      // If user canceled the document selection
      alert(
        DocumentPicker.isCancel(error)
          ? "Canceled"
          : "Unknown Error: " + JSON.stringify(error)
      );
    }
  };

  const _uploadFile = async () => {
    try {
      // Check if file selected
      if (Object.keys(filePath).length == 0)
        return alert("Please Select any File");
      setLoading(true);

      // Create Reference
      console.log(filePath.uri.replace("file://", ""));
      console.log(filePath.name);
      const reference = storage().ref(
        `/myfiles/${filePath.name}`
      );

      // Put File
      const task = reference.putFile(
        filePath.uri.replace("file://", "")
      );
      // You can do different operation with task
      // task.pause();
      // task.resume();
      // task.cancel();

      task.on("state_changed", (taskSnapshot) => {
        setProcess(
          `${taskSnapshot.bytesTransferred} transferred 
           out of ${taskSnapshot.totalBytes}`
        );
        console.log(
          `${taskSnapshot.bytesTransferred} transferred 
           out of ${taskSnapshot.totalBytes}`
        );
      });
      task.then(() => {
        alert("Image uploaded to the bucket!");
        setProcess("");
      });
      setFilePath({});
    } catch (error) {
      console.log("Error->", error);
      alert(`Error-> ${error}`);
    }
    setLoading(false);
  };

  return (
    <>
      {loading ? (
        <View style={styles.container}>
          <ActivityIndicator size="large" color="#0000ff" />
        </View>
      ) : (
        <SafeAreaView style={{ flex: 1 }}>
          <View style={styles.container}>
            <Text style={styles.titleText}>
              Upload Input Text as File on FireStorage
            </Text>
            <View style={styles.container}>
              <Text>
                Choose File and Upload to FireStorage
              </Text>
              <Text>{process}</Text>
              <TouchableOpacity
                activeOpacity={0.5}
                style={styles.buttonStyle}
                onPress={_chooseFile}
              >
                <Text style={styles.buttonTextStyle}>
                  Choose Image (Current Selected:{" "}
                  {Object.keys(filePath).length == 0
                    ? 0
                    : 1}
                  )
                </Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.buttonStyle}
                onPress={_uploadFile}
              >
                <Text style={styles.buttonTextStyle}>
                  Upload File on FireStorage
                </Text>
              </TouchableOpacity>
            </View>
            <Text style={styles.footerHeading}>
              React Native Firebase Cloud Storage
            </Text>
            <Text style={styles.footerText}>
              www.aboutreact.com
            </Text>
          </View>
        </SafeAreaView>
      )}
    </>
  );
};

export default UploadFileScreen;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    padding: 10,
  },
  titleText: {
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
    padding: 20,
  },
  buttonStyle: {
    alignItems: "center",
    backgroundColor: "orange",
    padding: 10,
    width: 300,
    marginTop: 16,
  },
  buttonTextStyle: {
    color: "white",
    fontWeight: "bold",
  },
  footerHeading: {
    fontSize: 18,
    textAlign: "center",
    color: "grey",
  },
  footerText: {
    fontSize: 16,
    textAlign: "center",
    color: "grey",
  },
});

页面/FilesListingScreen.js

// #3 Uploading Files and Images to Firebase Cloud Storage in React Native
// https://aboutreact.com/react-native-firebase-cloud-storage/

// Import React in our code
import React, { useState, useEffect } from "react";

// Import all the components we are going to use
import {
  SafeAreaView,
  StyleSheet,
  Text,
  View,
  ActivityIndicator,
  FlatList,
  Linking,
} from "react-native";

import storage from "@react-native-firebase/storage";
const FilesListingScreen = () => {
  // State Defination
  const (listData, setListData) = useState(());
  const (loading, setLoading) = useState(true);

  useEffect(() => {
    listFilesAndDirectories("");
  }, ());

  const listFilesAndDirectories = (pageToken) => {
    const reference = storage().ref("myfiles");
    reference.list({ pageToken }).then((result) => {
      result.items.forEach((ref) => {
        console.log("ref  ->>  ", JSON.stringify(ref));
      });

      if (result.nextPageToken) {
        return listFilesAndDirectories(
          reference,
          result.nextPageToken
        );
      }
      setListData(result.items);
      setLoading(false);
    });
  };

  const ItemView = ({ item }) => {
    return (
      // FlatList Item
      <View style={{ padding: 10 }}>
        <Text
          style={styles.item}
          onPress={() => getItem(item.fullPath)}
        >
          File Name: {item.name}
          {"\n"}
          File Full Path: {item.fullPath}
          {"\n"}
          Bucket: {item.bucket}
        </Text>
        <Text style={{ color: "red" }}>
          Click to generate Signed URL and Open it in
          browser
        </Text>
      </View>
    );
  };

  const ItemSeparatorView = () => {
    return (
      // FlatList Item Separator
      <View
        style={{
          height: 0.5,
          width: "100%",
          backgroundColor: "#C8C8C8",
        }}
      />
    );
  };

  const getItem = async (fullPath) => {
    const url = await storage()
      .ref(fullPath)
      .getDownloadURL()
      .catch((e) => {
        console.error(e);
      });
    Linking.openURL(url);
    console.log(url);
  };

  return (
    <SafeAreaView style={styles.container}>
      <Text style={styles.titleText}>
        Listing of Files from Cloud Storage
      </Text>
      {loading ? (
        <View style={styles.container}>
          <ActivityIndicator size="large" color="#0000ff" />
        </View>
      ) : (
        <FlatList
          data={listData}
          //data defined in constructor
          ItemSeparatorComponent={ItemSeparatorView}
          //Item Separator View
          renderItem={ItemView}
          keyExtractor={(item, index) => index.toString()}
        />
      )}
      <Text style={styles.footerHeading}>
        React Native Firebase Cloud Storage
      </Text>
      <Text style={styles.footerText}>
        www.aboutreact.com
      </Text>
    </SafeAreaView>
  );
};

export default FilesListingScreen;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    padding: 10,
  },
  titleText: {
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
    padding: 20,
  },
  footerHeading: {
    fontSize: 18,
    textAlign: "center",
    color: "grey",
  },
  footerText: {
    fontSize: 16,
    textAlign: "center",
    color: "grey",
  },
});

运行 React Native 应用程序

再次打开终端并使用跳转到您的项目。

cd ProjectName

1. 启动 Metro Bundler

首先,您需要启动 Metro,React Native 附带的 JavaScript 捆绑器。 要启动 Metro 捆绑程序,请运行以下命令

npx react-native start

一旦您启动 Metro Bundler,它将永远在您的终端上运行,直到您将其关闭。 让 Metro Bundler 在自己的终端中运行。 打开一个新终端并运行该应用程序。

2.启动React Native应用程序

在 Android 虚拟设备或真实调试设备上运行项目

npx react-native run-android

或在 iOS 模拟器上运行(仅限 macOS)

npx react-native run-ios

输出截图

React_native_firebase_cloud_storage1 React_native_firebase_cloud_storage2 React_native_firebase_cloud_storage3 React_native_firebase_cloud_storage4

React_native_firebase_cloud_storage5

React_native_firebase_cloud_storage6 React_native_firebase_cloud_storage7

这就是您如何在 Firebase Cloud Storage 上上传任何文件,并从适用于 Android 和 iOS 的 React Native 应用程序列出 Could Storage 中的文件。 如果您有任何疑问或想分享有关该主题的内容,您可以在下面发表评论或在此处联系我们。 很快就会有更多帖子发布。 敬请关注!

推荐:WP Review Slider Pro插件


发表评论