React Native 使用react-native-image-picker库实现图片上传功能
react-native-image-picker作为一个集成相机和相册的功能的第三方库,因为其使用相对简单受到前端开发人员的喜爱。
react-native-image-picker使用
1, 首先,安装下该插件。
npm install react-native-image-picker@latest --save
2, 针对Android和iOS平台分别进行配置
## android 平台配置
1,在android/settings.gradle文件中添加如下代码:
include ':react-native-image-picker'
project(':react-native-image-picker').projectDir = new File(settingsDir, '../node_modules/react-native-image-picker/android')
2,在android/app/build.gradle文件的dependencies中添加如下代码:
compile project(':react-native-image-picker')
3,在AndroidManifest.xml文件中添加权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
4,最后在MainApplication.Java文件中添加如下代码:
import com.imagepicker.ImagePickerPackage;
new ImagePickerPackage()
这样Android环境就配置好了。
iOS平台配置
1,打开Xcode打开项目,点击根目录,右键选择 Add Files to ‘XXX’,选中项目中的该路径下的文件即可:node_modules -> react-native-image-picker -> ios -> select RNImagePicker.xcodeproj
2,添加成功后使用link命令:react-native link react-native-image-picker 。 3,打开项目依次使用Build Phases -> Link Binary With Libraries将RNImagePicker.a添加到项目依赖。
4,对于iOS 10+设备,需要在info.plist中配置NSPhotoLibraryUsageDescription和NSCameraUsageDescription。
react-native-image-picker示例
为了项目使用的方便,我们将其封装为一个组件CameraButton.js。代码如下:
import React from 'react'
import {
TouchableOpacity,
StyleSheet,
Platform,
ActivityIndicator,
View,
Text,
ToastAndroid
} from 'react-native'
var ImagePicker = require('react-native-image-picker');
import Icon from 'react-native-vector-icons/Ionicons';
const options = {
title: '选择图片',
cancelButtonTitle: '取消',
takePhotoButtonTitle: '拍照',
chooseFromLibraryButtonTitle: '图片库',
cameraType: 'back',
mediaType: 'photo',
videoQuality: 'high',
durationLimit: 10,
maxWidth: 600,
maxHeight: 600,
aspectX: 2,
aspectY: 1,
quality: 0.8,
angle: 0,
allowsEditing: false,
noData: false,
storageOptions: {
skipBackup: true,
path: 'images'
}
};
class CameraButton extends React.Component {
constructor(props){
super(props);
this.state = {
loading:false
}
}
render() {
const {photos,type} = this.props;
let conText;
if(photos.length > 0){
conText = (<View style={styles.countBox}>
<Text style={styles.count}>{photos.length}</Text>
</View>);
}
return (
<TouchableOpacity
onPress={this.showImagePicker.bind(this)}
style={[this.props.style,styles.cameraBtn]}>
<View>
<Icon name="md-camera" color="#aaa" size={34}/>
{conText}
</View>
</TouchableOpacity>
)
}
showImagePicker() {
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
console.log('User cancelled image picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else {
let source;
if (Platform.OS === 'android') {
source = {uri: response.uri, isStatic: true}
} else {
source = {uri: response.uri.replace('file://', ''), isStatic: true}
}
let file;
if(Platform.OS === 'android'){
file = response.uri
}else {
file = response.uri.replace('file://', '')
}
this.setState({
loading:true
});
this.props.onFileUpload(file,response.fileName||'未命名文件.jpg')
.then(result=>{
this.setState({
loading:false
})
})
}
});
}
}
const styles = StyleSheet.create({
cameraBtn: {
padding:5
},
count:{
color:'#fff',
fontSize:12
},
fullBtn:{
justifyContent:'center',
alignItems:'center',
backgroundColor:'#fff'
},
countBox:{
position:'absolute',
right:-5,
top:-5,
alignItems:'center',
backgroundColor:'#34A853',
width:16,
height:16,
borderRadius:8,
justifyContent:'center'
}
});
export default CameraButton;
然后在需要使用的地方引入。
import CameraButton from '../../component/huar/cameraButton'
<CameraButton style={styles.cameraBtn}
photos={[]}
onFileUpload={this.onFileUpload} />
点击上传事件:
onFileUpload(file, fileName){
return this.props.uploadAvatar({
id: this.props.user.ID,
type:'logo',
obj:'user',
corpId: this.props.cropId
}, file, fileName)}
Action请求代码:
function actions(dispatch) {
return {
fileUrl,fileName)=>dispatch(Actions.uploadAvatar(params, fileUrl,fileName))
}
}
actions中的uploadAvatar函数如下。
function uploadAvatar(params, fileUrl, fileName) {
return dispatch=> {
return UserService.uploadImage(params, fileUrl, fileName)
.then(result=> {
dispatch({
type: UPDATE_AVATAR,
path: result.path
})
return result
})
}
}
//UserService.uploadImage代码如下
export function uploadImage(params, fileUrl,fileName) {
return http.uploadFile(`${config.UploadImage}`, params, fileUrl,fileName)
}
UserService函数的http异步上传图片代码如下:
let queryString = require('query-string');
import Storage from './storage'
import {
Platform
} from 'react-native'
const os = Platform.OS;
async function uploadFile(url, params, fileUrl,fileName) {
let Access_Token = await Storage.getItem('Access_Token');
let data = new FormData();
data.append('file', {
uri: fileUrl,
name: fileName,
type: 'image/jpeg'
});
Object.keys(params).forEach((key)=> {
if (params[key] instanceof Date) {
data.append(key, value.toISOString())
} else {
data.append(key, String(params[key]))
}
});
const fetchOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Access_Token': Access_Token ? Access_Token : '',
'UserAgent':os
},
body: data
};
return fetch(url, fetchOptions)
.then(checkStatus)
.then(parseJSON)
}
封装上传
如果上面的实现看的比较复杂,那么我们做如下的封装:
let common_url = 'http://192.168.1.1:8080/'; //服务器地址
let token = ''; //用户登陆后返回的token
function uploadImage(url,params){
return new Promise(function (resolve, reject) {
let formData = new FormData();
for (var key in params){
formData.append(key, params[key]);
}
let file = {uri: params.path, type: 'application/octet-stream', name: 'image.jpg'};
formData.append("file", file);
fetch(common_url + url, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data;charset=utf-8',
"x-access-token": token,
},
body: formData,
}).then((response) => response.json())
.then((responseData)=> {
console.log('uploadImage', responseData);
resolve(responseData);
})
.catch((err)=> {
console.log('err', err);
reject(err);
});
});
}
然后在使用的地方:
let params = {
userId:'abc12345', //用户id
path:'file:///storage/emulated/0/Pictures/image.jpg' //本地文件地址
}
uploadImage('app/uploadFile',params )
.then( res=>{
//请求成功
if(res.header.statusCode == 'success'){
//这里设定服务器返回的header中statusCode为success时数据返回成功
upLoadImgUrl = res.body.imgurl; //服务器返回的地址
}else{
//服务器返回异常,设定服务器返回的异常信息保存在 header.msgArray[0].desc
console.log(res.header.msgArray[0].desc);
}
}).catch( err=>{
//请求失败
})
附:http://lib.csdn.net/article/reactnative/58022?knId=1415 使用fetch+formData实现图片上传
- CSS3弹性盒布局
- iBatis.Net(4):DataMapper API
- PHP开发过程的那些坑(四) ——PDO bindParam函数
- iBatis.Net(3):创建SqlMapper实例
- PHP开发过程的那些坑(五) ——PHP的empty()
- iBatis.Net(2):基本概念与配置
- ASP.NET Web API中的依赖注入什么是依赖注入ASP.NET Web API依赖解析器使用Unity解析依赖配置依赖解析
- 解决Entity Framework查询匿名对象后的跨域访问的一种方式
- WebSocket在ASP.NET MVC4中的简单实现
- 在ASP.NET MVC中使用Unity进行依赖注入的三种方式第一种方法第二种方法第三种方法
- Unity Container中的几种注册方式与示例1.实例注册2.简单类型注册
- 使用Unity创建依赖注入依赖注入生命周期:注册、解析、销毁 注册解析销毁
- 使用WCF进行跨平台开发之三(JAVA调用WCF服务)1.开发必备2.生成WCF客户端3.开发程序4.结束语
- 使用WCF进行跨平台开发之二(IIS托管WCF服务并使用php平台调用)1.系统必备2.在IIS中托管WCF服务3.使用PHP调用托管在IIS中的WCF服务
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 消息队列之推还是拉,RocketMQ 和 Kafka是如何做的?
- Nginx系列:root与alias指令用法的区别
- Redis系列:Linux下部署Redis 6.x 版本
- 分布式锁的封装也很有讲究呀
- PHP与SEO,应用curl及正则获取搜狗搜索相关关键词
- Kafka经典面试题,你都会吗?
- 提高单细胞分析准确度的工具之一:Self-assembling manifolds
- 一不小心肝出了4W字的Redis面试教程
- 双向LSTM-CRF模型用于序列标注
- 容器服务 TKE 上服务暴露的几种方式
- 【论文分享】ACL 2020 信息抽取任务中的新动向
- 工匠人iOS 代码规范
- 写一个通用的幂等组件,我觉得很有必要
- PC性能监测工具,您不可或缺的好帮手~~
- 特征工程之处理时间序列数据