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

使用Firebase Storage上传后调用getDownloadURL报storage/object-not-found错误

Firebase Storage上传后调用getDownloadURL偶尔报object-not-found的解决方法

我在用Firebase Storage的uploadBytesResumable接口上传文件,之后调用getDownloadURL获取下载链接时,偶尔会遇到以下错误:

Firebase Storage: Object 'storatge_data/9d668c90-8381-4161-b9f1-d016f9b51837/files/xxx.m4a' does not exist. (storage/object-not-found)

我尝试通过判断字节传输完成来避免提前调用getDownloadURL:

if ((snapshot.bytesTransferred !== snapshot.totalBytes)) {
  return of(null)
}

但问题仍然偶尔出现,我的完整代码如下:

const newUploadFiles = (files: File[], updateDocRef: DocumentReference<DocumentData>) => {
  const resUpload = [...uploadFilesImage]
  from(files).pipe(
    mergeMap((file, i: number) => {
        const storageRef = ref(storage, `storatge_data/${id}/files/${file.name}`)
        const uploadTask = uploadBytesResumable(storageRef, file)
        return fromEventPattern((handler) =>
            uploadTask.on('state_changed', handler)
        ).pipe(
            mergeMap((snapshot: any) => {
                const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
                resUpload[i].progress = parseInt(progress.toFixed(0))

                setProressFiles((prev) => ([...prev, resUpload[i]]))

                if ((snapshot.bytesTransferred !== snapshot.totalBytes)) {
                    return of(null)
                }

                return from(getDownloadURL(snapshot.ref)).pipe(
                    mergeMap(url => {
                        const type = classifyFile(file.name)
                        let setType: any = of(null)
                        if (type === 'music') {
                            setType = onDrop(file)
                        }
                        return from(setType).pipe(
                            map(fileDetail => ({
                                file: url,
                                type,
                                fileDetail,
                                hash: "",
                                fileType: file.name.substring(file.name.lastIndexOf('.')),
                                fileName: file.name
                            }))
                        )
                    })
                )
            }),
            takeWhile(data => data === null, true),
            filter(each => each !== null)
        )
    }),
    toArray(),
    concatMap(data => {
        return from(updateDoc(updateDocRef, { files: data }))
    })
).subscribe()
}

问题原因

仅通过bytesTransferred === totalBytes判断上传完成并不严谨——即使字节传输完毕,Firebase Storage可能还在进行文件的最终校验、持久化或元数据写入操作,此时文件并未完全就绪,调用getDownloadURL就会触发找不到文件的错误。

正确的做法应该是监听上传任务的**success状态**,这是Firebase官方确认上传完全完成的标志。

修复方案

修改代码,通过snapshot.state判断上传状态,仅在状态为'success'时才执行getDownloadURL逻辑:

const newUploadFiles = (files: File[], updateDocRef: DocumentReference<DocumentData>) => {
  const resUpload = [...uploadFilesImage]
  from(files).pipe(
    mergeMap((file, i: number) => {
        const storageRef = ref(storage, `storatge_data/${id}/files/${file.name}`)
        const uploadTask = uploadBytesResumable(storageRef, file)
        return fromEventPattern((handler) =>
            uploadTask.on('state_changed', handler)
        ).pipe(
            mergeMap((snapshot: any) => {
                const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
                resUpload[i].progress = parseInt(progress.toFixed(0))
                setProressFiles((prev) => ([...prev, resUpload[i]]))

                // 仅当上传状态为success时才继续后续逻辑
                if (snapshot.state !== 'success') {
                    return of(null)
                }

                return from(getDownloadURL(snapshot.ref)).pipe(
                    mergeMap(url => {
                        const type = classifyFile(file.name)
                        let setType: any = of(null)
                        if (type === 'music') {
                            setType = onDrop(file)
                        }
                        return from(setType).pipe(
                            map(fileDetail => ({
                                file: url,
                                type,
                                fileDetail,
                                hash: "",
                                fileType: file.name.substring(file.name.lastIndexOf('.')),
                                fileName: file.name
                            }))
                        )
                    })
                )
            }),
            takeWhile(data => data === null, true),
            filter(each => each !== null)
        )
    }),
    toArray(),
    concatMap(data => {
        return from(updateDoc(updateDocRef, { files: data }))
    })
).subscribe()
}

关键修改点

  1. 替换判断条件:将bytesTransferred !== totalBytes改为snapshot.state !== 'success',确保只有上传任务完全完成后才调用getDownloadURL。
  2. 利用Firebase官方的状态机制,避免依赖字节数这种可能存在延迟的判断逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:37:04