美文网首页React Native学习全端之路
react-native-image-picker图片上传

react-native-image-picker图片上传

作者: 街角仰望 | 来源:发表于2017-10-13 11:00 被阅读732次

    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://blog.csdn.net/xiangzhihong8/article/details/72981936
    http://blog.csdn.net/codetomylaw/article/details/52446786

    相关文章

      网友评论

        本文标题:react-native-image-picker图片上传

        本文链接:https://www.haomeiwen.com/subject/zgjhjxtx.html