最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I use firebase storage from a client side React app? - Stack Overflow

programmeradmin0浏览0评论

I'm trying to write a file into cloud storage from within my React app. I created a new React app using the create-react-app tool. I believe I have followed the correct instructions to get a storage reference, with code like this: this.storage = firebase.storage();. But, no matter how I configure firebase and no matter what I import, I see this error: TypeError: _this.firebase.storage() is not a function..

I tried importing @firebase/storage (commented out here) but this results in an error, and the NPM page for that module suggests this is not something a user should ever load directly.

I believe I added the proper firebase libraries. I can use firestore and the legacy database (I removed the code to do it, but it works if I use something like this.firestore = this.firebase.firestore();). But, storage is unresolved.

I'm a little unclear as to whether I should be using client libraries for cloud storage (I believe that is exactly the same thing as "storage" for Firebase). But, all the examples seem to be for accessing storage from a NodeJS app, and I want to write the file from within my browser context as client-side JavaScript.

My package.json looks like this:

{
  "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"
  }
}

My index.js looks like this:

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",
    databaseURL: "",
    projectId: "abcdefg",
    storageBucket: "abcdefg.appspot",
    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')
);

The firebase config is copied from the Firebase console (but changed here).

I'm trying to write a file into cloud storage from within my React app. I created a new React app using the create-react-app tool. I believe I have followed the correct instructions to get a storage reference, with code like this: this.storage = firebase.storage();. But, no matter how I configure firebase and no matter what I import, I see this error: TypeError: _this.firebase.storage() is not a function..

I tried importing @firebase/storage (commented out here) but this results in an error, and the NPM page for that module suggests this is not something a user should ever load directly.

I believe I added the proper firebase libraries. I can use firestore and the legacy database (I removed the code to do it, but it works if I use something like this.firestore = this.firebase.firestore();). But, storage is unresolved.

I'm a little unclear as to whether I should be using client libraries for cloud storage (I believe that is exactly the same thing as "storage" for Firebase). But, all the examples seem to be for accessing storage from a NodeJS app, and I want to write the file from within my browser context as client-side JavaScript.

My package.json looks like this:

{
  "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"
  }
}

My index.js looks like this:

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')
);

The firebase config is copied from the Firebase console (but changed here).

Share Improve this question asked Jul 7, 2018 at 5:57 xrdxrd 4,0697 gold badges33 silver badges41 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 10

This works: $ npm i @firebase/storage --save.

This currently results in "@firebase/storage": "^0.2.3" inside package.json.

If I have that, I can use code like this in my firebaseConfig.js file to setup storage inside firebase:

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

Then code like this works:

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 );
      });
});

You're not importing firebase-storage, so that means the service won't be available in your code.

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

The rest of your code looks fine, once you add this dependency.

First you need to add firebase to your app

npm i firebase

or

yarn add firebase

Please check in your package.json if the version of your firebase is >9.0 because I will talk about that only.

By this time I also expect you to already have registered your app in Firebase console and have got your credentials. If not so then do that first.

In /src/ folder of your project add a new file 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;

In place of the FIREBASE_CONFIG place your credentials object.

Next make a new file to create a function

// 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;
    }
  }
}

If you only want the function only copy paste the function from here.

Now this files prop will accept an array of files / images and it will give back urls which is an array of links where you can access the uploaded files.

Here the storage is the same as which I exported from earlier.

A sample to call this function I have also showed here.

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>
  );
}
发布评论

评论列表(0)

  1. 暂无评论