React-native文件上传

上一篇说了文件选择的使用,

https://blog.csdn.net/qq_20652771/article/details/82184005

选了文件就要上传,这篇就记录一下文件上传

这是antd的一个UI库,不知道的同学自行去学习,选择图片和拍照有时间在补上,他们的上传方法是同一个,还包含了一点点RN和webview的交互以及组件封装调用

https://rn.mobile.ant.design/components/toast-cn/

1、调用各自文件选择方式

  延迟调用文件选择是为了用户体验,以及权限获取延时问题

React-native文件上传_第1张图片

2、上传前的一些处理

我们不能让用户传一些乱七八糟的东西上去,所以要对文件进行筛选,我们就简陋的用文件后缀名筛选一下就行了

React-native文件上传_第2张图片

4、调用上传文件的方法

this.props.sendWebMessage(fileList)这是上传成功后和WebView交互,有时间会记一下RN和WebView的交互

React-native文件上传_第3张图片

5、这是上传方法

其中必须的的参数,参数名不能改,如果上传的文件是中文名,还要对name字段编码(后台接收需要解码,才能得到真正的文件名),不然会报类似的错误

unexpected char 0*6587 at 34 in content-disposition

React-native文件上传_第4张图片

 

 

引用组件的代码片段

/**
 * @Date:   2018-08-08T17:25:36+08:00
 * @Email:  [email protected]
 * @Last modified time: 2018-08-23T08:17:26+08:00
 */

import React, { Component } from 'react';
import { StyleSheet, View, Text, WebView, AsyncStorage} from 'react-native';
import { deviceWidth ,isIOS,deviceHeight } from '../../../utils/common';
import { _Download } from '../../../utils/downloadImage';
import { connect } from 'react-redux';
import {ActionSheet, Toast} from "antd-mobile-rn";
import Header from "../../../components/Common/Header";
import Modal from "../../../components/Common/Modal";
import NoDate from "../../../components/Common/NoDate";
import NoMore from "../../../components/Common/NoMore";
import LoadingMore from "../../../components/Common/LoadingMore";


const isIPhone = new RegExp('\\biPhone\\b|\\biPod\\b', 'i').test(window.navigator.userAgent);
let wrapProps;
if (isIPhone) {
  wrapProps = {
    onTouchStart: e => e.preventDefault(),
  };
}



class Outweb extends Component {

  constructor(props){
    super(props);
    this.state = {
      visible:false,
       // url: "http://..../appjump"
       // url: "http://..../appjump"
       url: "http://..../appjump"
    }
  }

  async componentDidMount(){
     let token = await  AsyncStorage.getItem('token')
     let url = `${this.state.url}?token=${token}`
     this.setState({url:url.replace(/"/g,'')})
     console.log(url.replace(/"/g,''));
  }
  // 开始加载
  onLoadStart(e){
     Toast.loading('加载中...', 0)
  }
  // 加载成功
  onLoad (){
    Toast.hide()
  }
  // 加载失败
  onError(e){
    Toast.hide()
    this.props.navigation.goBack()
    Toast.info('应用加载失败,请稍后重试',2)
  }

  // 上传组件 getMessage
  onMessage(e){
      const message = e.nativeEvent.data
      if(message === 'upload'){
        Toast.loading('加载中...',0)
        this.setState({visible:true})
      }else {
        // console.log('*************',message);
        _Download(message);
      }
  }
   // 回调
   sendWebMessage(fileList){
      this.refs.webview.postMessage(fileList);
   }

  render(){
    return(
      
      
{this.props.navigation.goBack();Toast.hide()}}>
) } } const styles = StyleSheet.create({ page:{ flex:1, backgroundColor:"#fff", }, webView: { height: isIOS ? (deviceHeight-44):(deviceHeight-64), width: deviceWidth }, }) export default connect(({cstmrModel, loading}) => ({ cstmrModel, loading:loading.models.cstmrModel }))(Outweb)

 

组件代码

/**
 * @Date:   2018-08-21T15:52:02+08:00
 * @Email:  [email protected]
 * @Last modified time: 2018-08-23T09:51:26+08:00
 */

 import React from "react";
 import { connect } from 'react-redux'
 import {
 	View,
 	Text,
 	StyleSheet,
 	Image,
 	TouchableOpacity
 } from "react-native";
import { activeOpacity ,acceptFile } from "../../utils/common";
import { ActionSheet, Toast, Modal} from "antd-mobile-rn";
import ImagePicker from 'react-native-image-crop-picker';
import RNFileSelector from 'react-native-file-selector';
import { FileUpload } from '../../utils/FileUpload'
import RNFS from 'react-native-fs'

const isIPhone = new RegExp('\\biPhone\\b|\\biPod\\b', 'i').test(window.navigator.userAgent);
let wrapProps;
if (isIPhone) {
  wrapProps = {
    onTouchStart: e => e.preventDefault(),
  };
}

 class UploadModal extends React.PureComponent {
   	constructor(props) {
   		super(props);
      this.state={
          visible:false
      }
   	}

    componentWillUnmount(){
        ImagePicker.clean().then(() => {
            console.log('clean file cache');
          }).catch(e => {
            console.log(e);
        });
    }

    async fileUpload(fileAry) {
      Toast.loading('上传中...',0)
      try {
        const res = await FileUpload(fileAry)
        if (res.success) {
            let fileList = JSON.stringify(res.attList)
            this.props.sendWebMessage(fileList)
            Toast.hide()
        }else {
            Toast.hide()
            Toast.info(res.message,2)
        }
      } catch (e) {
        Toast.hide()
        // console.log(e);
      }
    }
    // file上传
    upLoadFile(){
        let that = this;
        Toast.hide()
        RNFileSelector.Show( {
            title: '选择文件',
            closeMenu: true,
            onDone: (path) => {
              let params = [{
                    mime:'',
                    path:`file://${path}`
                }]
                let fileArr = path.split('.');
                if (fileArr.length > 1 && acceptFile.indexOf(fileArr[fileArr.length-1]) !==-1) {
                    params.mime = `.${fileArr[fileArr.length-1]}`
                    // console.log('params*****',params);
                    that.fileUpload(params)
                }else {
                    Toast.info('文件类型错误,请重新选择!',2);
                }
            },
            onCancel: () => {
                console.log('cancelled')
            }
        })
    }
    // image上传
    upLoadImage(params){
        let that = this;
        Toast.hide()
        if (params==='camera') {
            ImagePicker.openCamera({
                width: 300,
                height: 400,
                multiple: true,
                hideBottomControls:true,
              }).then(image => {
                this.fileUpload(image)
            }).catch((e)=>{
                Toast.info('未选择文件或文件异常!',2)
            });
        }else {
            ImagePicker.openPicker({
                mediaType:'photo',
                multiple: true
            }).then(images => {
                that.fileUpload(images)
            }).catch((e)=>{
                Toast.info('未选择文件或文件异常!',2)
            });
        }
    }

    showActionSheet(){
        Toast.hide();
        let that = this;
        const BUTTONS = [
          '拍摄',
          '选择图片',
          '选择文件',
          '取消',
        ];
        ActionSheet.showActionSheetWithOptions(
          {
            maskClosable:false,
            options: BUTTONS,
            cancelButtonIndex: 3,
          },
          (buttonIndex: any) => {
              if (BUTTONS[buttonIndex]==='拍摄') {
                  Toast.loading('加载中...',0)
                  this.timer = setTimeout(()=>{that.upLoadImage('camera')},200)
              }else if (BUTTONS[buttonIndex]==='选择图片') {
                  Toast.loading('加载中...',0)
                  that.timer = setTimeout(()=>{that.upLoadImage()},200)
              }
              else if (BUTTONS[buttonIndex]==='选择文件') {
                  Toast.loading('加载中...',0)
                  that.timer = setTimeout(()=>{that.upLoadFile()},200)
              }
          },
        );
    }

   	render() {
      const { visible } =  this.props
   		return (
          
          {
            visible ? this.showActionSheet():null
          }
          
   		);
   	}
 }

 const styles = StyleSheet.create({
    content:{
        flexDirection:'row',
        justifyContent:'space-around',
        alignItems:'center'
    },
    img:{
        height:60,
        width:60,
    }
 });

 export default connect(({ M_My }) => ({
 	M_My
 }))(UploadModal);

上传组件代码


import { AsyncStorage } from 'react-native';
import RequestUrl from "../services/RequestUrl";
import { Storage } from "../utils";

const baseUrl = async () => {
  .....
}

export const FileUpload = async(fileAry) => {
    let formData = new FormData();
    let token = await AsyncStorage.getItem('token');
    let serverUrl = await baseUrl();
    if (!fileAry.length) return {success:false,message:'未选择文件'};
    //因为需要上传多个文件,所以需要遍历数组,把文件的路径数组放入formData中
    for( let i = 0; i < fileAry.length; i++ ){
        let path = fileAry[i].path;
        let arr = path.split('/');//截取获取文件名
        // 文件的类型,以及中文文件名编码
        let file = { uri: path, type: 'multipart/form-data', name: escape(arr[arr.length-1]), fileType: fileAry[i].mime };   //这里的key(uri和type和name)不能改变,
        formData.append("file", file);   //这里的files就是后台需要的key
        //这里的files就是后台需要的key
    }
    // console.log(formData);
    let response = await fetch(`${serverUrl}${RequestUrl.FILE_UPLOAD}`,{
        method:'POST',
        headers:{
             // 'Accept': 'Application/json',
            'Content-Type':'multipart/form-data',
            'token': token,
            'moduelType':8
        },
        body:formData,
    })
    // console.log('response',await response.json());
    return await response.json();
}

你可能感兴趣的:(React-native,前端)