React Native 使用react-native-image-picker庫實現圖片上傳功能

來源:互聯網
上載者:User

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 = '';   //使用者登陸後返回的tokenfunction 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實現圖片上傳

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.