react-native-image-picker圖片上傳

react-native-image-picker作為一個(gè)集成相機(jī)和相冊(cè)的功能的第三方庫(kù)却舀,因?yàn)槠涫褂孟鄬?duì)簡(jiǎn)單受到前端開(kāi)發(fā)人員的喜愛(ài)肾请。

react-native-image-picker使用

1, 首先,安裝下該插件寓免。

npm install react-native-image-picker@latest --save

2, 針對(duì)Android和iOS平臺(tái)分別進(jìn)行配置

android 平臺(tái)配置

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文件中添加權(quán)限:

<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環(huán)境就配置好了牢撼。

iOS平臺(tái)配置

1,打開(kāi)Xcode打開(kāi)項(xiàng)目,點(diǎn)擊根目錄,右鍵選擇 Add Files to ‘XXX’,選中項(xiàng)目中的該路徑下的文件即可:node_modules -> react-native-image-picker -> ios -> select RNImagePicker.xcodeproj



2疑苫,添加成功后使用link命令:react-native link react-native-image-picker 熏版。
3纷责,打開(kāi)項(xiàng)目依次使用Build Phases -> Link Binary With Libraries將RNImagePicker.a添加到項(xiàng)目依賴。



4撼短,對(duì)于iOS 10+設(shè)備再膳,需要在info.plist中配置NSPhotoLibraryUsageDescription和NSCameraUsageDescription。

react-native-image-picker示例

為了項(xiàng)目使用的方便曲横,我們將其封裝為一個(gè)組件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: '圖片庫(kù)', 
    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} />
點(diǎn)擊上傳事件:
    onFileUpload(file, fileName){
        return this.props.uploadAvatar({
            id: this.props.user.ID,
            type:'logo',
            obj:'user',
            corpId: this.props.cropId
        }, file, fileName)}
 Action請(qǐng)求代碼:
function actions(dispatch) {
    return {
        fileUrl,fileName)=>dispatch(Actions.uploadAvatar(params, fileUrl,fileName))
    }
}

actions中的uploadAvatar函數(shù)如下禾嫉。

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函數(shù)的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)
}

封裝上傳

如果上面的實(shí)現(xiàn)看的比較復(fù)雜灾杰,那么我們做如下的封裝:

let common_url = 'http://192.168.1.1:8080/';  //服務(wù)器地址
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=>{
        //請(qǐng)求成功
        if(res.header.statusCode == 'success'){
            //這里設(shè)定服務(wù)器返回的header中statusCode為success時(shí)數(shù)據(jù)返回成功
            upLoadImgUrl = res.body.imgurl;  //服務(wù)器返回的地址
        }else{
             //服務(wù)器返回異常,設(shè)定服務(wù)器返回的異常信息保存在 header.msgArray[0].desc
            console.log(res.header.msgArray[0].desc);
        }
    }).catch( err=>{ 
         //請(qǐng)求失敗
    })

參考:
http://blog.csdn.net/xiangzhihong8/article/details/72981936
http://blog.csdn.net/codetomylaw/article/details/52446786

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末熙参,一起剝皮案震驚了整個(gè)濱河市吭露,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌尊惰,老刑警劉巖讲竿,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異弄屡,居然都是意外死亡题禀,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門膀捷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)迈嘹,“玉大人,你說(shuō)我怎么就攤上這事全庸⌒阒伲” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵壶笼,是天一觀的道長(zhǎng)神僵。 經(jīng)常有香客問(wèn)我,道長(zhǎng)覆劈,這世上最難降的妖魔是什么保礼? 我笑而不...
    開(kāi)封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮责语,結(jié)果婚禮上炮障,老公的妹妹穿的比我還像新娘。我一直安慰自己坤候,他們只是感情好胁赢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著白筹,像睡著了一般智末。 火紅的嫁衣襯著肌膚如雪谅摄。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天吹害,我揣著相機(jī)與錄音,去河邊找鬼虚青。 笑死它呀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的棒厘。 我是一名探鬼主播纵穿,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼奢人!你這毒婦竟也來(lái)了谓媒?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤何乎,失蹤者是張志新(化名)和其女友劉穎句惯,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體支救,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抢野,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了各墨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片指孤。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贬堵,靈堂內(nèi)的尸體忽然破棺而出恃轩,到底是詐尸還是另有隱情,我是刑警寧澤黎做,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布叉跛,位于F島的核電站,受9級(jí)特大地震影響蒸殿,放射性物質(zhì)發(fā)生泄漏昧互。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一伟桅、第九天 我趴在偏房一處隱蔽的房頂上張望敞掘。 院中可真熱鬧,春花似錦楣铁、人聲如沸玖雁。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赫冬。三九已至浓镜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間劲厌,已是汗流浹背膛薛。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留补鼻,地道東北人哄啄。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像风范,于是被迫代替她去往敵國(guó)和親咨跌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容