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