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;
                    }
                })
            }
        })
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值