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 librarylet 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上传文件至阿里云ossconst 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;}})}})}