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

React Native安卓端同时选择图片视频的社区解决方案咨询

React Native 双端同时选择图片和视频并上传方案

一、社区现成方案(优先推荐)

RN Image Picker 的 mediaType: 'mixed' 仅在 iOS 生效,安卓端可通过以下成熟社区库实现同时选图+视频:

1. react-native-image-crop-picker

该库支持安卓、iOS 双端同时选择图片与视频,配置简单:

  • 安卓权限配置(在 AndroidManifest.xml 添加):
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- Android 13+ 需补充以下权限 -->
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    
  • RN 端调用示例:
    import ImagePicker from 'react-native-image-crop-picker';
    
    const pickMedia = async () => {
      try {
        const media = await ImagePicker.openPicker({
          mediaType: 'any', // 同时支持图片、视频选择
          multiple: true, // 开启多选
          maxFiles: 10, // 可选:限制最大选择数量
        });
        // media 数组包含选中文件的路径、MIME 类型等信息
        await uploadMedia(media);
      } catch (error) {
        console.error('媒体选择失败:', error);
      }
    };
    

2. react-native-document-picker

若需更灵活的文件筛选(不限于媒体类型),可使用该库:

  • RN 端调用示例:
    import DocumentPicker from 'react-native-document-picker';
    
    const pickMedia = async () => {
      try {
        const results = await DocumentPicker.pickMultiple({
          type: [
            DocumentPicker.types.images,
            DocumentPicker.types.videos,
          ],
        });
        await uploadMedia(results);
      } catch (error) {
        if (DocumentPicker.isCancel(error)) {
          console.log('用户取消选择');
        } else {
          console.error('选择失败:', error);
        }
      }
    };
    

二、原生 Kotlin 自定义方案(社区库不满足需求时)

如果需要高度定制选择界面或逻辑,可自行开发安卓原生模块:

1. 创建安卓原生模块

在 android/app/src/main/java/com/yourproject/ 下新建 MediaPickerModule.kt:

package com.yourproject

import android.app.Activity
import android.content.Intent
import android.net.Uri
import com.facebook.react.bridge.*
import com.facebook.react.modules.core.DeviceEventManagerModule

class MediaPickerModule(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
    private val REQUEST_CODE = 1001
    private var promise: Promise? = null

    override fun getName(): String {
        return "MediaPickerModule"
    }

    @ReactMethod
    fun pickMedia(promise: Promise) {
        this.promise = promise
        val currentActivity = currentActivity ?: run {
            promise.reject("NO_ACTIVITY", "当前无可用Activity")
            return
        }

        val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
            type = "*/*"
            putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "video/*"))
            putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
            addCategory(Intent.CATEGORY_OPENABLE)
        }

        currentActivity.startActivityForResult(intent, REQUEST_CODE)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            val mediaList = Arguments.createArray()
            data?.clipData?.let { clipData ->
                for (i in 0 until clipData.itemCount) {
                    val uri = clipData.getItemAt(i).uri
                    val mediaMap = Arguments.createMap().apply {
                        putString("uri", uri.toString())
                        putString("type", reactContext.contentResolver.getType(uri))
                    }
                    mediaList.pushMap(mediaMap)
                }
            } ?: data?.data?.let { uri ->
                val mediaMap = Arguments.createMap().apply {
                    putString("uri", uri.toString())
                    putString("type", reactContext.contentResolver.getType(uri))
                }
                mediaList.pushMap(mediaMap)
            }
            promise?.resolve(mediaList)
        } else {
            promise?.reject("CANCELLED", "用户取消选择或选择失败")
        }
        promise = null
    }
}

2. 注册模块

新建 MediaPickerPackage.kt:

package com.yourproject

import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager

class MediaPickerPackage : ReactPackage {
    override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
        return listOf(MediaPickerModule(reactContext))
    }

    override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
        return emptyList()
    }
}

在 MainApplication.kt 的 getPackages() 中添加模块:

override fun getPackages(): List<ReactPackage> {
    return PackageList(this).packages.apply {
        add(MediaPickerPackage())
    }
}

3. RN 端调用原生模块

import { NativeModules } from 'react-native';
const { MediaPickerModule } = NativeModules;

const pickMedia = async () => {
    try {
        const media = await MediaPickerModule.pickMedia();
        await uploadMedia(media);
    } catch (error) {
        console.error('媒体选择失败:', error);
    }
};

三、同步上传实现

获取媒体文件后,通过 FormData 完成上传:

import { Platform } from 'react-native';

const uploadMedia = async (mediaList) => {
    const formData = new FormData();
    mediaList.forEach((media, index) => {
        formData.append(`media[${index}]`, {
            uri: Platform.OS === 'ios' ? media.uri.replace('file://', '') : media.uri,
            type: media.type,
            name: `media_${index}.${media.type.split('/')[1]}`,
        });
    });

    try {
        const response = await fetch('https://your-upload-api.com', {
            method: 'POST',
            headers: {
                'Content-Type': 'multipart/form-data',
            },
            body: formData,
        });
        const result = await response.json();
        console.log('上传成功:', result);
    } catch (error) {
        console.error('上传失败:', error);
    }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:45:57