React + Firebase 存储 + 文件上传和进度显示

Posted

技术标签:

【中文标题】React + Firebase 存储 + 文件上传和进度显示【英文标题】:React + Firebase Storage + File upload and progress display 【发布时间】:2018-01-19 10:47:24 【问题描述】:

我一直在关注这个上传恶作剧的 Firebase 存储图像。我被困住了。我该如何显示上传进度?我刚刚意识到使用状态可能不是要走的路,因为我会一遍又一遍地调用 setState。你有想法吗?

我想我需要某种递归函数,但我在哪里调用它?我不能在 Promise 中调用它可以吗?

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

【问题讨论】:

【参考方案1】:

终于在 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;
);

干杯。

【讨论】:

如果您不使用状态,您将如何更新 值? 如果您愿意,可以保存进度以说明...如果我没记错的话,我在这个项目上使用的是 mobx(已经有一段时间了) 这给我带来了巨大的数字:(【参考方案2】:
firebase
  .storage()
  .ref(`images/$directory/$file.name`)
  .put(file)
  .on(
    "state_changed",
    (snapshot) => 
      const progress = Math.round(
        (snapshot.bytesTransferred / snapshot.totalBytes) * 100
      );
      this.setState( progress );
    ,
    (error) => this.setState( error: error.message )
  );

【讨论】:

以上是关于React + Firebase 存储 + 文件上传和进度显示的主要内容,如果未能解决你的问题,请参考以下文章

使用 Firestore 通过“react-redux-firebase”存储配置文件数据?

为啥我没有在我的 react 应用程序中获取 firebase 存储文件 url?

React + Firebase 存储 + 文件上传和进度显示

使用 react native expo 将文件上传到 firebase 存储

使用 Firebase 实时数据库和 React 将图像上传给用户 [重复]

React-Native:从 Firebase 存储下载图像