You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase文件上传无法使用.on()监听进度问题求助

问题解决:uploadtask.on is not a function

错误根源

你使用的uploadBytes是Firebase Storage的简单上传方法,它返回的是Promise对象,没有.on()方法用于监听上传状态。要实现进度追踪,必须使用支持可恢复上传的uploadBytesResumable方法,该方法返回UploadTask实例,这个实例才具备.on()状态监听能力。

修复步骤

1. 修改导入语句

将uploadBytes替换为uploadBytesResumable:

import {ref, uploadBytesResumable, listAll, getDownloadURL} from "firebase/storage"

2. 更新上传逻辑

把uploadBytes调用改为uploadBytesResumable,保留状态监听逻辑:

const upLoadImage = () =>{
  if (imageUpload ==null) return;
  const imageRef = ref(proStorage, `images/${imageUpload.name + v4()}`)     
  
  // 替换uploadBytes为uploadBytesResumable
  const uploadtask = uploadBytesResumable(imageRef, imageUpload)
  uploadtask.on('state_changed', (snapshot) => {
    const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log('Upload is ' + progress + '% done');
    switch (snapshot.state) {
      case 'paused':
        console.log('Upload is paused');
        break;
      case 'running':
        console.log('Upload is running');
        break;
    }
  }, 
  (error) => {
    console.error('上传失败:', error);
  }, 
  () => {
    getDownloadURL(uploadtask.snapshot.ref).then((downloadURL) => {
      console.log('File available at', downloadURL);
      alert('Image Uploaded')
    });
  }
);
}

3. 调整提示位置

将alert('Image Uploaded')移到上传成功的回调中,避免上传未完成就弹出提示。

完整修正后的Uploadform组件代码

import React, { useEffect, useState } from 'react';
import {proStorage} from '../firebase/config';
import {ref, uploadBytesResumable, listAll, getDownloadURL} from "firebase/storage"
import { v4  } from 'uuid';

const Uploadform = () => {
  const [imageUpload, setImageUpload] = useState(null)
  const [imageList,setImageList] = useState([])
  const [uploadProgress, setUploadProgress] = useState(0) // 新增进度状态

  const upLoadImage = () =>{
    if (imageUpload ==null) return;
    const imageRef = ref(proStorage, `images/${imageUpload.name + v4()}`)     
    
    const uploadtask = uploadBytesResumable(imageRef, imageUpload)
    uploadtask.on('state_changed', (snapshot) => {
      const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
      setUploadProgress(Math.round(progress))
      console.log('Upload is ' + progress + '% done');
      switch (snapshot.state) {
        case 'paused':
          console.log('Upload is paused');
          break;
        case 'running':
          console.log('Upload is running');
          break;
      }
    }, 
    (error) => {
      console.error('上传出错:', error);
      alert('上传失败,请重试')
    }, 
    () => {
      getDownloadURL(uploadtask.snapshot.ref).then((downloadURL) => {
        console.log('File available at', downloadURL);
        // 上传完成后直接更新图片列表
        setImageList(prev => [...prev, downloadURL])
        alert('Image Uploaded')
        setUploadProgress(0)
        setImageUpload(null)
      });
    }
  );
  }

  const imageListRef = ref(proStorage, "images/")
  useEffect(() => {
    listAll(imageListRef).then((response) => {
      response.items.forEach((item) => {
        getDownloadURL(item).then((url) => {
          setImageList((prev) => [...prev,url])
        })
      })
    })
    // eslint-disable-next-line
  },[])

  return (
    <div className='absolute h-full w-full flex justify-center items-center'>
      <div className='h-[50%] w-[50%] justify-center items-center border'>
        <div className='h-full w-full flex flex-col items-center justify-center gap-4'>
          <input 
            type='file' 
            onChange={(e) => {setImageUpload(e.target.files[0])}}
          />
          {uploadProgress > 0 && <p>上传进度:{uploadProgress}%</p>}
          <button className='bg-black text-white' onClick={upLoadImage} disabled={!imageUpload}>Upload Image</button>
        </div>
        <div className='flex flex-wrap gap-2 mt-4'>
          {imageList.map((url, index) => {
              return <img key={index} src={url} alt='uploaded-img' className='w-24 h-24 object-cover'></img>
            })}
        </div>
      </div>
    </div>
  )
}

export default Uploadform

额外说明

  • Firebase v9+采用模块化API设计,将上传功能拆分为uploadBytes(简单上传,无进度监听)和uploadBytesResumable(可恢复上传,支持状态监听、暂停/恢复操作)
  • 如需暂停或恢复上传,可调用uploadtask.pause()和uploadtask.resume()方法

内容的提问来源于stack exchange,提问作者Brian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:14:52