react-native 上傳圖片和視頻到阿里雲, 帶進度條

圖片描述

實現上面的效果須要的庫以下react

react-native-image-picker
react-native-progressspring

先來講下是如何實現點擊上傳圖標彈出optionModal上傳選項的動畫的.
圖片描述react-native

整個optionModal區域是一個Animated.View, render 的時候他的position 是 absolute的, 整個位置是隱藏在屏幕下的, bottom: - 200. 點擊按鈕以後,用Animated.spring 把 bottom 的值 調整到 0 , 這樣隱藏的部分就彈出來了。app

const styles = StyleSheet.create({
  container: {
    backgroundColor: theme.screen_background_color,
    zIndex: 100,
    height: 200,
    width: '100%',
    position: 'absolute',
    bottom: -  200),
    backgroundColor: 'rgb(255,255,255)',
    alignItems: 'center',
    borderTopWidth: 1,
    borderTopColor: theme.divider_color,
  }

  showOptionModal() {
    Animated.spring(
      this.modalPos, { toValue: 0, }
    ).start();

<Animated.View style={[styles.container, { bottom: this.modalPos }]}>
 </Animated.View>

還有就是區域裏面的upload video 和 upload photos 圖標動畫有個前後順序,這裏的處理就是upload video 這個圖標用了個settimeout, 讓他的動畫觸發晚了個 0.1秒而已。實現的方法也是跟optionModal彈出的方法同樣。ide

接下來就是選擇手機裏面的圖片或者視頻了,這裏咱們會用一個庫叫作 react-native-image-picker, 這個庫應該是你們很常常會使用到的, 就是選擇手機裏面的視頻和圖片,或者能夠用攝像頭拍攝圖片. 當咱們點擊 upload photos 的時候, 觸發下面的代碼就能夠開始選擇圖片了動畫

ImagePicker.showImagePicker({
      title: null,
      cancelButtonTitle: 'cancel',
      allowsEditing: true,
      chooseFromLibraryButtonTitle: 'choose from camera roll',
      takePhotoButtonTitle: type==='video'?null:'open camera',
      mediaType: type,
      noData: true,
      quality: 0.5,
      videoQuality: 'medium',
      storageOptions: {
        skipBackup: true,
        cameraRoll: true,
        waitUntilSaved: true,
      },
    }, (response) => {
      if (!response.didCancel && !response.error) {
        //能夠在這裏上傳圖片了
        this.startUpload(response);
      }
      return null;
    });
  }

圖片描述

當圖片選擇完畢以後, 就會觸發this.startUpload(response); 了, 下面就是如何處理圖片上傳阿里雲的部分了。 在上傳文件到阿里雲oss 以前呢 須要從Oss獲取幾個配置項,OSSAccessKeyId,Signature,key, police, 能夠看下Oss 文檔,這個須要你本身搞定啦。this

startUpload(response){
        const uploadMediaData = new FormData();
        uploadMediaData.append('OSSAccessKeyId', accessKeyId);
        uploadMediaData.append('policy', policy);
        uploadMediaData.append('Signature', signature);
        uploadMediaData.append('key', key);
        uploadMediaData.append('success_action_status', 201);
        uploadMediaData.append('file', {
          uri:  response.uri,
          type: 'multipart/form-data',
          name: response.fileName,
        });

        // 上傳成功 
        successResponse = (xhr) => {
          let returnKey = xhr.responseText.match(/<Key>([^<]*)<\/Key>/)[1];
          //這個key 就是你上傳文件在oss 的地址了, 
        };
        //上傳失敗
        failResponse = () => {
            // to do
        };

        //開始上傳
       const OSS_UPLOAD_URI = 'http://xxxxx.oss-us-east-1.aliyuncs.com'
        futch(OSS_UPLOAD_URI, {
          method: 'POST',
          body: uploadMediaData,
          extra: null,
        }, (progressEvent) => {
        // progress 就是上穿的進度, 更新 state 裏面的uploadProgress
          const progress = (progressEvent.loaded / progressEvent.total);
          this.setState({
            uploadProgress: progress,
          })
        }, (xhr) => successResponse(xhr), failResponse)
          .then((res) => console.log(res), (err) => console.log('error' + err));
}

//這個方法就是具體上傳的代碼了
futch = (url, opts = {}, onProgress, successResponse, failResponse) => {
  return new Promise((res, rej) => {
    let xhr = new XMLHttpRequest();
    xhr.open(opts.method || 'get', url);
    for (let k in opts.headers || {})
      xhr.setRequestHeader(k, opts.headers[k]);
    xhr.onload = e => res(e);
    xhr.onreadystatechange = (e) => {
      if (xhr.readyState !== 4) {
        return;
      }
      //阿里雲的狀態碼201 纔有返回的信息
      if (xhr.status === 201) {
        xhr.extra = opts.extra;
        successResponse(xhr);
      } else {
        xhr.extra = opts.extra;
        failResponse(xhr);
      }
    };
    xhr.onerror = rej;
    if (xhr.upload && onProgress)
      xhr.upload.onprogress = onProgress;
    xhr.setRequestHeader('Content-Type', 'multipart/form-data');
    xhr.send(opts.body);
  });
}

若是一切都ok 的話, 這個時候在上傳的過程當中就應該出現進度條了,
上面提到了,this.state.uploadProgress 是用來存儲上傳進度的, 咱們就利用這個做爲進度條的數據源了, 由於咱們用的是圓形的進度條,這裏須要另一個庫, ' react-native-progress'.阿里雲

import ProgressCircle from 'react-native-progress/Circle';

//render 的時候只要把this.state.uploadProgress 丟進去就好了
         <ProgressCircle size={30}
              showsText={true}
              size={100}
              progress={uploadProgress}
              color={‘#32CDFF’}
              thickness={4}
              borderWidth={2}
              style={styles.progressCircle}
            />

圖片描述

這裏特別提出一下,oss 的上傳成功的返回代碼是201。這樣整個過程就結束了, 其中有些細節沒提出來,須要你們本身完善,可是大概的流程應該都寫出來了. 但願對大你們有用。url

相關文章
相關標籤/搜索