如何从客户端 React 应用程序使用 firebase 存储?

How do I use firebase storage from a client side React app?

我正在尝试从我的 React 应用程序中将文件写入云存储。我使用 create-react-app 工具创建了一个新的 React 应用程序。我相信我已按照正确的说明获取存储参考,代码如下:this.storage = firebase.storage();。但是,无论我如何配置 firebase 以及无论我导入什么,我都会看到此错误:TypeError: _this.firebase.storage() is not a function.

我尝试导入 @firebase/storage(在此处注释掉)但这会导致错误,并且该模块的 NPM 页面表明这不是用户应该直接加载的内容。

我相信我添加了正确的 firebase 库。我可以使用 firestore 和遗留数据库(我删除了执行此操作的代码,但如果我使用 this.firestore = this.firebase.firestore(); 之类的东西,它就可以工作)。但是,存储尚未解决。

我不太清楚是否应该使用客户端库进行云存储(我认为这与 "storage" 用于 Firebase 完全相同)。但是,所有示例似乎都是为了从 NodeJS 应用程序访问存储,我想从我的浏览器上下文中将文件作为客户端 JavaScript.

我的 package.json 看起来像这样:

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@firebase/app": "^0.3.2",
    "@firebase/auth": "^0.5.2",
    "@firebase/firestore": "^0.5.6",
    "@material-ui/core": "^1.3.1",
    "@material-ui/icons": "^1.1.0",
    "enzyme": "^3.3.0",
    "enzyme-adapter-react-16": "^1.1.1",
    "react": "^16.4.1",
    "react-dom": "^16.4.1"
  },
  "scripts": {
    "start": "PORT=3009 react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

我的 index.js 看起来像这样:

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import firebase from '@firebase/app';
import '@firebase/firestore';
import '@firebase/auth';
//import '@firebase/storage';                                                                                                                  

var config = {
    apiKey: "ABCDEFG",
    authDomain: "abcdefg.firebaseapp.com",
    databaseURL: "https://abcdefg.firebaseio.com",
    projectId: "abcdefg",
    storageBucket: "abcdefg.appspot.com",
    messagingSenderId: "12345"
};

firebase.initializeApp(config);

class Index extends Component {

    constructor(props) {
        super(props);
        this.state = {};
        this.firebase = firebase;
        this.firestore = this.firebase.firestore(); // This works fine.
        this.storage = this.firebase.storage(); // This fails
        console.log( "Got storage ref" );
    }

    render() {
        return (
            <div>
                Hello
            </div>
        )
    }
}

ReactDOM.render(
        <Index/>,
    document.getElementById('react-container')
);

firebase 配置是从 Firebase 控制台复制的(但在此处更改)。

您没有导入 firebase-storage,这意味着该服务在您的代码中不可用。

"@firebase/storage": "^5.1.0",

添加此依赖项后,其余代码看起来没问题。

有效:$ npm i @firebase/storage --save

这目前导致 "@firebase/storage": "^0.2.3"package.json 内。

如果我有,我可以在我的 firebaseConfig.js 文件中使用这样的代码来设置 firebase 中的存储:

import firebase from '@firebase/app';
import '@firebase/firestore';
import '@firebase/auth';
import '@firebase/storage';

那么这样的代码就可以工作了:

const storage = firebase.storage();
const files = [ 'image1.png', 'image2.png' ]; 
files.map( filename => {
    storage
      .ref( `/covers/${filename}` )
      .getDownloadURL()
      .then( url => {
        console.log( "Got download url: ", url );
      });
});

首先您需要将 firebase 添加到您的应用程序

npm i firebase

yarn add firebase

如果您的 firebase 版本是 >9.0,请检查您的 package.json,因为我只会谈论那个。

此时我还希望您已经在 Firebase 控制台中注册了您的应用程序并获得了您的凭据。如果不是这样,那么先做。

在项目的 /src/ 文件夹中添加一个新文件 firebase.js

// src/firebase.js

import firebase from "firebase/compat/app";
import { FIREBASE_CONFIG } from "./constants/firebase";
import "firebase/compat/storage";

firebase.initializeApp(FIREBASE_CONFIG);
export const storage = firebase.storage();
export default firebase;

代替 FIREBASE_CONFIG 放置您的凭据对象。

接下来新建一个文件来创建函数

// src/services/firebase/firebase.service.js

import React, { useState } from "react";
import { storage } from "../../firebase";

export class FirebaseService {
  uploadToFirebaseStorage(files = []) {
    let urls = [];
    if (files.length > 0) {
      files.map((file) => {
        const uploadTask = storage.ref(`/img/${file.name}`).put(file);
        uploadTask.on(
          "state_changed",
          (snapshot) => {
            const progress = Math.round(
              (snapshot.bytesTransferred / snapshot.totalBytes) * 100
            );
          },
          (error) => {
            console.log(error);
          },
          () => {
            storage
              .ref("img")
              .child(file.name)
              .getDownloadURL()
              .then((newUrl) => {
                urls.push(newUrl);
                console.log(newUrl);
              });
          }
        );
      });
      return urls;
    }
  }
}

如果您只想要该功能,只需从此处复制粘贴该功能。

现在这个 files 道具将接受一组文件/图像,它会返回 urls 这是一组链接,您可以在其中访问上传的文件。

这里的storage和我之前导出的一样

调用此函数的示例我也已在此处显示。

src/App.js

import React, { useState } from "react";
import { FirebaseService } from "./services/firebase/firebase.service";

export default function App() {
  const [files, setFiles] = useState([]);
  const fbs = new FirebaseService();
  return (
    <React.Fragment>
      <input
        type={"file"}
        onChange={(e) => {
          let temp = files;
          temp.push(e.target.files[0]);
          setFiles(temp);
        }}
      ></input>
      <button
        onClick={() => {
          console.log("Hi");
          fbs.uploadToFirebaseStorage(files);
        }}
      >
        Upload
      </button>
    </React.Fragment>
  );
}