web-dev-qa-db-ja.com

React + Firebase Storage +ファイルのアップロードと進行状況の表示

私はこのfirebaseストレージイメージをアップロードするshenaniganを突っついています。私は立ち往生しています。アップロードの進行状況を表示するにはどうすればよいですか? setStateを何度も呼び出すので、stateを使用するのはおそらく道のりではないことに気づきました。アイデアは?

ある種の再帰関数が必要だと思いますが、どこで呼び出すのですか?約束の中でそれを呼ぶことはできませんか?

// You'll need to set the rules to allow un-authed uploading however.
// Here's how to allow public: goto your firebase console and select the storage tab then the rules tab and change to:
//
// service firebase.storage {
//  match /b/{bucket}/o {
//    match /{allPaths=**} {
//      allow read, write;
//    }
//  }
// }
//
//
// I just threw together an infinite grow animation here for shits, however, I use styled components in my own app so I will access the this.state.percent value in the "actual" animation.

const config = {
    apiKey: "KEY",
    authDomain: "DOMAIN",
    databaseURL: "DB_URL",
    projectId: "ID",
    storageBucket: "BUCKET",
    messagingSenderId: "MSG_ID"
};

firebase.initializeApp(config);
const storageRef = firebase.storage().ref()

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      uploading: false,
      percent: 0,
      file: '',
      error: ''
    }
    this.handleFileSelect = this.handleFileSelect.bind(this)
    this.handleFileUpload = this.handleFileUpload.bind(this)
  }
  handleFileSelect(e) {
    this.setState({file: e.target.files[0]})
  }
  handleFileUpload() {
    this.setState({uploading: true})
    storageRef.child('images')
      .put(this.state.file)
      .then(snap => {
        this.setState({uploading: false})
        // the loading percent logic here?
        // how do i keep tabs on the percent?
      })
      .catch(err => this.setState({error: err.message}))
  }
  render() {
    return (
      <div className='container'>
        <div className='form'>
          <input type='file' onChange={this.handleFileSelect}/>
          <button onClick={this.handleFileUpload}>Upload</button>
        </div>
        {this.state.uploading 
          ? <div>
              <div className='load-bar'/>
              <span>Uploading: {this.state.percent}%</span>
            </div>
          : ''
        }
        <pre>
          <code>
            {this.state.error ? <span className='error'>{this.state.error}</span> : ''}
            {JSON.stringify(this.state.file, null, 2)}
          </code>
        </pre>
      </div>
    )
  }
}

ReactDOM.render(<App/>, document.getElementById('root'))
body {
  background: #212121;
  color: #dbdbdb;
}

.form {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  padding: 1rem;
  margin: 1rem;
  background: rgba(0,0,0,0.4);
}

.error {
  font-size: 14px;
  text-align: center;
  color: red;
}

.load-bar {
  height: 20px;
  width: 0px;
  background: Lime;
  animation: grow 5s linear forwards;
}

@keyframes grow {
  from {
    width: 0px;
  }
  to {
    width: 100%;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.2.0/firebase.js"></script>

<div id='root'></div>
8
archae0pteryx

最後に、Firebaseのドキュメント(すべての場所)で答えが見つかりました。図に行きます。

これがスキニーミニーです:

var uploadTask = storageRef.child('images/rivers.jpg').put(file);

// Register three observers:
// 1. 'state_changed' observer, called any time the state changes
// 2. Error observer, called on failure
// 3. Completion observer, called on successful completion
uploadTask.on('state_changed', function(snapshot){
  // Observe state change events such as progress, pause, and resume
  // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
  var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
  console.log('Upload is ' + progress + '% done');
  switch (snapshot.state) {
    case firebase.storage.TaskState.PAUSED: // or 'paused'
      console.log('Upload is paused');
      break;
    case firebase.storage.TaskState.RUNNING: // or 'running'
      console.log('Upload is running');
      break;
  }
}, function(error) {
  // Handle unsuccessful uploads
}, function() {
  // Handle successful uploads on complete
  // For instance, get the download URL: https://firebasestorage.googleapis.com/...
  var downloadURL = uploadTask.snapshot.downloadURL;
});

乾杯。

10
archae0pteryx