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
相关产品推荐
相关产品推荐

