RN上传文档组件react-native-file-selector

1,RN上传文档组件react-native-file-selector这一篇文档是前两篇文档的前提,这里做了上传后,后面就可以执行下载、查看等后续操作。
2,我用这个组件的原因是两端通用,而且可以展示文件选择目录,唯一不足的就是我们的需求想要做上传文档的大小控制在5M以内的时候这个控件里实现不了,所以想了其他的办法实现的,后面我会讲到
3,react-native-file-selector组件Github地址
4,RN下载文档
5,RN查看文档

  • 具体的安装什么的我也不多说了,跟着官网一点点实现就可以了,问题不大,下面就切入主题看看我写的代码段

1,上传的文件选择处理:
(1)此处涉及的代码有上传文档大小的判断,由于没有找到合适的方法获取文件大小,所以就采取原生方法获取文件大小
(2)文件选择的文件夹内容显示的时候做了个过滤,打开的文件里就都是你需要的文档类型了,注意下IOS和安卓过滤条件是相反的

//上传文档,type=0表示上传的照片,1表示上传的文档
    _onPressDocument = () => {
        this.props.close();
        let filterFile;
        if (Platform.OS === 'ios') { //文件夹内容筛选IOS和安卓是相反的,要注意
            filterFile = ['log','LOG','HTML','html','js','JS','bat','BAT','class','CLASS','java','JAVA','PRO','pro','sql','SQL'];
        } else if (Platform.OS === 'android') {
            filterFile = ".+(.pdf|.PDF|.doc|.DOC|.DOCX|.docx|.xls|.xlsx|.XLS|.XLSX|.ppt|.PPT|.PPTX|.pptx|.txt|.TXT|.rar|.RAR|.zip|.ZIP)$";
        }
        //文档目录
        RNFileSelector.Show({
            title: '选择文件',
            closeMenu: true,
            filter: filterFile,
            onDone: (path) => {
                // android上通过'react-native-file-selector获取的path是不包含file://'协议的,
                // android上需要拼接协议为'file://'+ path,
                // 而IOS则不需要,type可以是文件的MIME类型或者'multipart/form-data'
                let Path = Platform.OS === 'ios' ? path : `file://${path}`;
                let fileParams = {mime: '', path: Path}
                let fileArr = path.split('.');
                console.log('fileArr: ', fileArr);
                if (fileArr.length > 1 && acceptFile.indexOf(fileArr[fileArr.length - 1]) !== -1) {
                    let checkFilePath = Platform.OS === 'ios'?Path:path;
                    FaceModule.getFileSize(checkFilePath).then((result)=>{ //根据文件路径获取文件大小
                        console.log("rs->",result)
                        if (!_.isEmpty(result)&& parseFloat(result) <= 5) {  //文件小于5M继续下一步
                            fileParams.mime = `.${fileArr[fileArr.length - 1]}`
                            console.log('fileParams: ', fileParams);
                            this.FileUpload(fileParams)
                        } else {
                            this._showToast(); //提示文档超过5M,重新选择
                        }
                    });
                } else {
                    Toast.info('文件类型错误,请重新选择!', 2000);
                }
            },
            onCancel: () => {
                console.log('cancelled')
            }
        })
    }

安卓生获取文件大小:这里注意传过来的path前面不要加file://,当时没注意传过来的是带file://,获取不到文件大小,后来检查发现的

/**
     *  根据路径获取文件大小(单位M,保留2位小数)
     * @param path    指定路径即可(注意传过来的路径不要带file://)
     * @param promise
     */
    @ReactMethod
    public void getFileSize(String path, Promise promise) {
        String sizeMb = "";
        try {
            Log.e("FAceM", "path: " + path);
            File mfile = new File(path); // "/storage/emulated/0/文档7M.pdf"
            Log.e("FAceM", "size: " + mfile.length());
            //FileInputStream fis = new FileInputStream(mfile);

            FileInputStream fis = new FileInputStream(mfile);

            DecimalFormat df = new DecimalFormat("#.##");

            sizeMb = df.format((double) ((double) fis.available() / 1024 / 1024));

            Log.e("FaceModule", sizeMb);
            //fis.close();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("FAceM", "path: " + path);
            sizeMb = null;
        }
        promise.resolve(sizeMb);
    }

2,上传文档的接口请求

//formData上传,type=0表示上传的照片,1表示上传的文档
    FileUpload(fileParams) {
        get_item(APP_DATA).then((data1) => {
            // if (!_.isEmpty(data)) {
            if (!_.isEmpty(fileParams)) {
                //因为需要上传多个文件,所以需要遍历数组,把文件的路径数组放入formData中
                // for (let i = 0; i < fileAry.length; i++) {
                let path = fileParams.path;
                let arr = path.split('/');//截取获取文件名为数组

                // 文件的类型,以及中文文件名编码
                //这里的key(uri和type和name)不能改变
                let params = {
                    uri: path, name: arr[arr.length - 1], //取文件夹下的文件名  name: arr[arr.length - 1],
                    fileType: fileParams.mime
                };
                let access_token = data1.ACCESS_TOKEN
                let uid = data1.UID
                ModalIndicator.show('上传中...')
                _postFile('application/v3/campus/topic/upload', params, uid, access_token,
                    data => {
                        ModalIndicator.hide()
                        console.log('file data: ', data)
                        if (data.code == 0) {
                            //给H5的参数
                            let source = {
                                type: "1",
                                file_name: arr[arr.length - 1],
                                mime: fileParams.mime,
                                file_id: data.data.file_id
                            }
                            this.props.selPhoto(source)
                            console.log('file source: ', source)
                        }
                    }, err => {
                        ModalIndicator.hide()
                        console.log('data err:', err)
                    })
            } else {
                ModalIndicator.hide()
                Toast.info('未选择文件', 200)
                return
            }
            // }
        });
    }

3,接口请求处理,这里当时写完后选择的文件名为中文就报错,英文就没事,所以结合后端解决了这个问题

/**
 *  schoolForum 上传文档
 * @param uri  路径
 * @param name 文件名
 * @param fileType 文件类型
 * @param url 接口地址
 * @param access_token token
 * @param successCallback 接口返回
 * @param failCallback  接口失败返回
 * @private
 */
export function _postFile(url, params, uid, access_token, successCallback, failCallback) {
    let formData = new FormData()
    let file = {  
// 文件的类型,以及中文文件名编码 
//(encodeURIComponent、charset=utf-8、Content-Transfer-Encoding)等解决选择的文件的文件名为中文的时候报错问题
//要配合后端解析来用,后端童鞋懂的
        uri: params.uri,
        type: 'multipart/form-data;charset=utf-8',
        name: encodeURIComponent(params.name),
        fileType: params.fileType
    } //这里的key(uri和type和name)不能改变

    // 调用文件上传的方法 formData.append(key,value)
    // file是字段名,根据后端接受参数的名字来定,
    // android上通过'react-native-file-selector获取的path是不包含file://'协议的,
    // android上需要拼接协议为'file://'+ path,
    // 而IOS则不需要,type可以是文件的MIME类型或者'multipart/form-data'
    formData.append('file', file); //这里的files就是后台需要的key
    console.log("file",file)
    let postUrl = BASE_URL + url + "?file_type=224005"
    let fetchOptions = {  //解决选择的文件的文件名为中文的时候报错
        method: 'POST',
        headers: {
            'uid': uid,
            'access_token': access_token,
            'Content-Type': 'multipart/form-data;charset=utf-8', 
            'Content-Transfer-Encoding':'utf-8', 
        },
        body: formData
    }
    fetch(postUrl, fetchOptions)
        .then((response) => response.json())
        .then((responseJSON) => {
            if (responseJSON.msg && responseJSON.msg == 'ok') {
                successCallback(responseJSON)
            } else {
                if (failCallback) {
                    failCallback(responseJSON)
                }
            }
        }).catch(function (err) {
        if (failCallback) {
            failCallback(err)
        }
    });
}

4,头部导入组件使用,上传文件过滤

import RNFileSelector from 'react-native-file-selector'

const acceptFile = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'rar', 'zip','PDF', 'DOC', 'DOCX', 'XLS', 'XLSX', 'PPT', 'PPTX', 'TXT', 'RAR' ,'ZIP']

组件使用介绍完毕!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容