react native(expo)选择图片/视频并上传阿里云oss

1.引入相关库:

复制代码
@ant-design/react-native ant风格UI库
expo-file-system 文件访问
expo-image-picker 图片/视频选择器

2.新建图片选择并上传的帮助类

复制代码
import { Toast } from '@ant-design/react-native';
import * as FileSystem from "expo-file-system";
import * as ImagePicker from 'expo-image-picker';
import AppService from "../api/app";
import Loading from "../components/ui/Loading";
import LogUtil from "./log_util";

// 从后端api获取
export let ossUrl = 'https://oss-2008.oss-cn-hongkong.aliyuncs.com';
let ossConfig = null;

/**
 * @desc 选择相册图片
 */
export const pickImage = async (mediaTypes = ImagePicker.MediaTypeOptions.Images) => {
    // No permissions request is necessary for launching the image library
    let result = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: mediaTypes,
        allowsEditing: true,
        aspect: null,
        quality: 0.5,
    });

    LogUtil.log('pick image result = ', result);

    if (result.canceled) {
        return null;
    }
    if (mediaTypes === ImagePicker.MediaTypeOptions.Images) {
        if (result.assets[0]?.fileSize/(1024*1024) > 2) {
            Toast.fail('图片不能超过2MB');
            return null;
        }
    } else if (mediaTypes === ImagePicker.MediaTypeOptions.Videos) {
        if (result.assets[0]?.fileSize/(1024*1024) > 10) {
            Toast.fail('视频不能超过10MB');
            return null;
        }
    } else {}

    return result.assets[0].uri;
};

export const uploadImage = async (fileName, filePath, nav) => {
    Loading.show();
    // 从后端获取阿里云oss相关凭证
    const res = await AppService.getAliyunOssToken({}, nav);
    if (res.code === 200) {
        /*
        *
        * host = obj['host']
            policyBase64 = obj['policy']
            accessid = obj['accessid']
            signature = obj['signature']
            expire = parseInt(obj['expire'])
            callbackbody = obj['callback']
            key = obj['dir']
        *
        *  */
        ossConfig = res.data;
        ossUrl = ossConfig['host'];
    } else {
        Loading.hide();
        Toast.info('获取oss token信息失败')
        return null;
    }

    if (filePath && filePath.length > 0) {
        const split = filePath.split('.');
        let realFileName = (!fileName || fileName.length === 0) ? `${random_string()}.${split[split.length - 1]}` : `${fileName}.${split[split.length - 1]}`;
        let key = `${ossConfig['dir']}${realFileName}`;
        let imageServicePath = `${ossConfig['host']}/${key}`;

        try {
            LogUtil.log('ossUrl = ', ossUrl)
            // 使用FileSystem.uploadAsync上传文件至阿里云oss
            const response = await FileSystem.uploadAsync(`${ossUrl}`, filePath, {
                fieldName: 'file',
                httpMethod: 'POST',
                uploadType: FileSystem.FileSystemUploadType.MULTIPART,
                parameters: {
                    'name': realFileName,
                    'key': key,
                    'policy': ossConfig['policy'],
                    'OSSAccessKeyId': ossConfig['accessid'],
                    'success_action_status': '200',
                    'callback': ossConfig['callback'],
                    'signature': ossConfig['signature']
                }
            })

            LogUtil.log('response', JSON.stringify(response), 'imageServicePath', imageServicePath)
            Loading.hide();
            if (response.status !== 200) {
                return null;
            }
            return { imageServicePath, fileName: key };
        } catch (error) {
            LogUtil.error(error)
        }
    }
    Loading.hide();
    return null;
}

const random_string = (len) => {
    len = len || 32;
    let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
    let maxPos = chars.length;
    let pwd = '';
    for (let i = 0; i < len; i++) {
        pwd += chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return pwd;
}

3.代码中调用:

3.1 只选择图片、视频后用于展示

复制代码
pickImage(mediaTypes).then(uri => {
            if (uri) {
                // uri可直接使用ImageView组件展示
            }
        })

3.2 选择图片、视频再上传阿里云oss后展示

复制代码
    const ChatTypes = {
        voice: 6,
        image: 2,
        video: 3,
        text: 1,
        systemTips: 4,
        autoText: 5,
    }    
    
    let imageSendValue = '';
    let videoSendValue = '';
    let imageUri = '';
    let videoUri = '';
    const pickAndUploadImage = (type) => {
        let mediaTypes = type === ChatTypes.image ? ImagePicker.MediaTypeOptions.Images : ImagePicker.MediaTypeOptions.Videos;
        pickImage(mediaTypes).then(uri => {
            if (uri) {
                uploadImage(null, uri, navigation).then(res => {
                    if (!res) {
                        Toast.info(i18n.t("Chat.UploadFail"));
                        return;
                    }
                    LogUtil.log('imageServicePath = ', res?.imageServicePath, 'fileName = ', res?.fileName)

                    switch (type) {
                        case ChatTypes.image:
                            imageSendValue = res?.fileName;
                            imageUri = uri;
                            // sendMessage(ChatTypes.image, imageSendValue, imageUri);
                            break;
                        case ChatTypes.video:
                            videoSendValue = res?.fileName;
                            videoUri = uri;
                            // sendMessage(ChatTypes.video, videoSendValue, videoUri);
                            break;
                        default:
                            break;
                    }
                })
            }
        })
    }
相关推荐
gaolei_eit1 小时前
Vue3项目ES6转ES5,兼容低版本的硬件设备,React也
javascript·react.js·es6
百锦再8 小时前
Reactive编程入门:Project Reactor 深度指南
前端·javascript·python·react.js·django·前端框架·reactjs
Ashley的成长之路8 小时前
2025 年最新:VSCode 中提升 React 开发效率的必备插件大全
ide·vscode·react.js·工作提效·react扩展
百锦再8 小时前
React编程高级主题:测试代码
android·前端·javascript·react.js·前端框架·reactjs
光影少年12 小时前
react的hooks防抖和节流是怎样做的
前端·javascript·react.js
m0_7190841113 小时前
React笔记张天禹
前端·笔记·react.js
lbb 小魔仙13 小时前
【HarmonyOS实战】React Native 表单实战:在 OpenHarmony 上构建高性能表单
react native·华为·harmonyos
Ziky学习记录13 小时前
从零到实战:React Router 学习与总结
前端·学习·react.js
青青家的小灰灰14 小时前
React 19 核心特性与版本优化深度解析
react.js
却尘15 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js