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

React Native iOS设备上传图片至Firebase Storage失败求助

React Native iOS真机上传Firebase Storage失败问题

问题描述

在React Native应用中将图片上传至Firebase Storage时,Android设备和iOS模拟器均可正常运行,但iOS真机上传失败,报错信息如下:

NativeFirebaseError: [storage/unknown] An unknown error has occurred. (underlying reason 'Can not finalize upload. Current size is 0. Expected final size is 201112.')

使用的库版本:react-native-image-crop-picker 0.38.0

选择图片代码

const choosePhotoFromLibrary = () => {
  ImagePicker.openPicker({
    width: 300,
    height: 300,
    cropping: true
  }).then((image) => {
      const imageUri = Platform.OS === 'ios' ? image.sourceURL : image.path
      console.log(imageUri)
  })
  .catch((e) =>{
      console.log(e)
  })
}

Firebase配置详情

Podfile配置

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

$RNFirebaseAsStaticFramework = true

platform :ios, '12.4'
install! 'cocoapods', :deterministic_uuids => false
use_frameworks! :linkage => :static


target 'zaater' do
  config = use_native_modules!

  #Storage troubleshooting
  pod 'Firebase/Core'
  pod 'Firebase/Auth'
  pod 'Firebase/Firestore'
  pod 'Firebase/Storage'

  # Flags change depending on the env values.xx
  flags = get_default_flags()

  use_react_native!(
    :path => config[:reactNativePath],
    # Hermes is now enabled by default. Disable by setting this flag to false.
    # Upcoming versions of React Native may rely on get_default_flags(), but
    # we make it explicit here to aid in the React Native upgrade process.
    :hermes_enabled => true,
    :fabric_enabled => flags[:fabric_enabled],
    # Enables Flipper.
    #
    # Note that if you have use_frameworks! enabled, Flipper will not work and
    # you should disable the next line.
    # :flipper_configuration => FlipperConfiguration.enabled,
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

  target 'zaaterTests' do
    inherit! :complete
    # Pods for testing
  end

  post_install do |installer|
    react_native_post_install(
      installer,
      # Set `mac_catalyst_enabled` to `true` in order to apply patches
      # necessary for Mac Catalyst builds
      :mac_catalyst_enabled => false
    )
    __apply_Xcode_12_5_M1_post_install_workaround(installer)
  end
end

AppDelegate.mm配置

#import <Firebase.h>

if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
}

已将GoogleService-info.plist文件添加至iOS目录(与Podfile同级),同时也添加到了Xcode项目中。

图片上传函数

const uploadImage =  async (image) => {
    try {
        const uploadUri = image
        let filename = uploadUri.substring(uploadUri.lastIndexOf('/') + 1)
    
        // Add timestamp to File Name
        const extension = filename.split('.').pop();
        const name = filename.split('.').slice(0, -1).join('.')
        filename = name + Date.now() + '.' + extension

        //Store image
        const storageRef = storage().ref(`users/${idx}/${filename}`)
        const task = storageRef.putFile(uploadUri)
       
        //get image URL after being downloaded to firebase storage
        await task
        const url = await storageRef.getDownloadURL()
        return url
    } catch (e) {
        console.log(e)
        return null
    }
}

解决方案

1. 修正iOS真机的图片URI处理

iOS真机上image.sourceURL是ph://格式的照片库URI,Firebase的putFile无法直接读取这种格式的文件,需改用image.path(沙盒本地路径):

const choosePhotoFromLibrary = () => {
  ImagePicker.openPicker({
    width: 300,
    height: 300,
    cropping: true,
    includeBase64: false,
    mediaType: 'photo'
  }).then((image) => {
      // iOS真机统一使用image.path
      const imageUri = image.path
      console.log(imageUri)
      uploadImage(imageUri)
  })
  .catch((e) =>{
      console.log(e)
  })
}

2. 配置iOS照片库权限

确保Info.plist中添加照片库访问权限声明:

<key>NSPhotoLibraryUsageDescription</key>
<string>需要访问您的照片库以上传图片</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>需要访问您的照片库以上传图片</string>

3. 改用Base64格式上传(备选方案)

如果沙盒路径仍无法读取,可将图片转为Base64后用putString上传:

const uploadImage = async (image) => {
    try {
        let uploadUri = image
        let filename = uploadUri.substring(uploadUri.lastIndexOf('/') + 1)
        const extension = filename.split('.').pop();
        const name = filename.split('.').slice(0, -1).join('.')
        filename = name + Date.now() + '.' + extension

        // 处理iOS的ph://格式URI
        if (Platform.OS === 'ios' && uploadUri.startsWith('ph://')) {
            const base64Data = await ImagePicker.readFile(uploadUri)
            const storageRef = storage().ref(`users/${idx}/${filename}`)
            const task = storageRef.putString(base64Data, 'base64', {
                contentType: `image/${extension}`
            })
            await task
            const url = await storageRef.getDownloadURL()
            return url
        } else {
            // 原有文件路径上传逻辑
            const storageRef = storage().ref(`users/${idx}/${filename}`)
            const task = storageRef.putFile(uploadUri)
            await task
            const url = await storageRef.getDownloadURL()
            return url
        }
    } catch (e) {
        console.log(e)
        return null
    }
}

4. 检查Firebase Storage规则

临时开放测试规则(上线后需修改为安全规则):

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if true;
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:45:29