react 类组件使用WebUploader

本文详细介绍了如何在React应用中集成WebUploader库,实现大文件的分片上传、断点续传、文件检查及秒传功能。通过WebUploader的注册回调和jQuery配合,处理文件上传的各个阶段,包括进度更新、成功与失败状态。同时,文章还提及了如何自定义UI和调整WebUploader样式,并提供了关键代码示例。
摘要由CSDN通过智能技术生成

0.效果

        实现了文件上传,删除,查看。查看功能是使用一个iframe打开一个上传文件之后,后端返回的网页。

 

 

1.安装相关库

(1)官网下载JS文件,下载 - Web Uploader

        下载的JS文件中包含各个版本的webuploader,可以按需引入。本项目仅需使用到的源文件为webuploader.css,webuploader.js、Uploader.swf

(2)js源文件放在react项目public目录下,然后index.html的script标签引入js文件。注意:由于webuploader使用了jquery,所以必须在webuploader之前引入jquuery

  <script type="text/javascript" src="http://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
  <link rel="stylesheet" href="./webuploader2/webuploader.css">
  <script type="text/javascript" src="./webuploader2/webuploader.js"></script>

(3)在index.html中将WebUploader挂载到window对象

<script type="text/javascript">
    console.log('WebUpLoader',WebUploader);
    window.WebUploader = WebUploader
</script>

(4)在组件中使用WebUploader 

const WebUploader = window.WebUploader

(5)项目使用antd UI,安装

        npm i antd 

2.webuploader组件

下面是react中的完整代码

import React, { Component } from 'react'
import { Card, Button, Row, Col, Divider, Progress, message, Modal } from 'antd';
import { nanoid } from 'nanoid'
import './index.scss'


import $ from 'jquery'

const WebUploader = window.WebUploader


export default class WebUpLoaderCom extends Component {
    uploader = null
    state = {
        uploader: {},
        fileList: [],     // file: {},把file对象也保存下来 progress ,status: 'START',statusName: '待开始',
        //上传的文件列表 file.id file.name
        showIframe: false,
    }

    componentDidMount() {
        let that = this
        var startDate;
        // HOOK 这个必须要再uploader实例化前面
        WebUploader.Uploader.register({
            // 在文件发送之前执行
            'before-send-file': 'beforeSendFile',
            // 在文件分片后,上传之前执行(如果没有启用分片,整个文件被当成一个分片)
            'before-send': 'beforeSend',
            // 在文件所有分片都上传完后,且服务端没有错误返回后执行
            "after-send-file": "afterSendFile"
        }, {
            beforeSendFile: function (file) {
                startDate = new Date();
                console.log("开始上传时间" + startDate)
                // console.log("beforeSendFile");
                // Deferred对象在钩子回掉函数中经常要用到,用来处理需要等待的异步操作。
                var deferred = WebUploader.Deferred();
                //1、计算文件的唯一标记MD5,用于断点续传
                uploader.md5File(file, 0, 3 * 1024 * 1024).progress(function (percentage) {
                    // 文件md5编码的进度
 
                }).then(function (val) { // 完成
                    console.log('File MD5 Result:', val);
                    file.md5 = val;
                    file.uid = WebUploader.Base.guid();
                    // 判断文件是否上传过,是否存在分片,断点续传
                    $.ajax({
                        type: "POST",
                        url: "http://ip:port/site_survey/bigfile/check",
                        async: false,
                        data: {
                            fileMd5: val
                        },
                        success: function (data) {
                            var resultCode = data.code;
                            // 秒传
                            if (resultCode === -1) {
                                // 文件已经上传过,忽略上传过程,直接标识上传成功;
                                uploader.skipFile(file);
                                file.pass = true;
                            } else {
                                //文件没有上传过,下标为0
                                //文件上传中断过,返回当前已经上传到的下标
                                file.indexcode = resultCode;
                            }
                        }, error: function () {

                        }
                    });
                    //获取文件信息后进入下一步
                    deferred.resolve();
                });
                return deferred.promise();
            },
            beforeSend: function (block) {
                //获取已经上传过的下标
                var indexchunk = block.file.indexcode;
                var deferred = WebUploader.Deferred();
                if (indexchunk > 0) {
                    if (block.chunk > indexchunk) {
                        //分块不存在,重新发送该分块内容
                        deferred.resolve();
                    } else {
                        //分块存在,跳过
                        deferred.reject();
                    }
                } else {
                    //分块不存在,重新发送该分块内容
                    deferred.resolve();
                }
                //返回Deferred的Promise对象。
                return deferred.promise();
            },
            afterSendFile: function (file) {
                //如果所有分块上传成功,则通知后台合并分块
                $.ajax({
                    type: "POST",
                    url: "http://ip:port/site_survey/bigfile/merge",
                    data: {
                        fileName: file.name,
                        fileMd5: file.md5
                    },
                    success: function (data) {
                        console.log('data', data);
                    }, error: function (error) {
                        console.log('error', error);
                    }
                });
            }
        });

        // 实例化
        var uploader = WebUploader.create({
            pick: {
                id: '#picker',
                label: '点击选择文件'
            },
            duplicate: true,//去重, 根据文件名字、文件大小和最后修改时间来生成hash Key
            swf: 'js/Uploader.swf',
            chunked: true,//开启分片
            chunkSize: 10 * 1024 * 1024, // 10M 每个分片的大小限制
            threads: 3,
            server: 'http://ip:port/site_survey/bigfile/upload',
            auto: false,
            // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
            disableGlobalDnd: true,
            fileNumLimit: 1024,
            fileSizeLimit: 50 * 1024 * 1024 * 1024,//50G 验证文件总大小是否超出限制, 超出则不允许加入队列
            fileSingleSizeLimit: 10 * 1024 * 1024 * 1024 //10G 验证单个文件大小是否超出限制, 超出则不允许加入队列
        });
        that.setState({      //把实例保存到state中
            uploader: uploader
        })
        // 当有文件被添加进队列的时候
        uploader.on('fileQueued', function (file) {
            let appendFile = that.state.fileList;
            let res = appendFile.some(item => {
                return item.file.name === file.name
            })
            if (res) {
                message.error(file.name + '文件重复。')
                return
            }
            appendFile.push({
                file: file,    //把file对象也保存下来
                fileId: file.id,
                progress: 0,
                status: 'START',
                statusName: '待开始',
            })
            that.setState({
                fileList: appendFile,
            })
        });

        uploader.onUploadBeforeSend = function (obj, data) {
            // console.log("onUploadBeforeSend",data);
            var file = obj.file;
            data.md5 = file.md5 || '';
            data.uid = file.uid;
        };
        // 上传中 用来记录上传进度
        uploader.on('uploadProgress', function (file, percentage) {
            let updateFileList = that.state.fileList;
            let res = updateFileList.map(item => {      //文件上传中时更新文件状态和进度条
                if (item.file.id === file.id) {
                    item.progress =  Math.floor(percentage * 100);

                    item.status = "UPLOADING";
                    item.statusName = "上传中";
                }
                return item
            })
            that.setState({
                fileList: res,
            })
        });
        // 上传成功后执行 失败不执行
        uploader.on('uploadSuccess', function (file) {
            console.log('suc file', file);
            let updateFileList = that.state.fileList;
            let res = updateFileList.map(item => {    //文件上传成功更新状态
                if (item.file.id === file.id) {
                    item.progress = 100;
                    item.status = "UPLOADED";
                    item.statusName = "已完成"
                }
                return item
            })
            that.setState({
                fileList: res,
            })
            var endDate = new Date();
            var time = (endDate - startDate) / 1000 + "s"
            var text = '已上传';
            if (file.pass) {
                text = "文件秒传功能,文件已上传。"
            }
            message.success(`${file.name} ${text},文件上传耗时${time}`)
        });

        //上传失败执行
        uploader.on('uploadError', function (file) {
            message.error(`${file.name}上传出错`)
        });
        //上传完成后 无论成功失败都执行
        uploader.on('uploadComplete', function (file) {

        });
    }
    //上传文件
    up = (item) => {
        return () => {
            const { uploader, fileList } = this.state;
            uploader.upload(item.file)
            let updateObj = fileList;
            let idx = fileList.indexOf(item);
            updateObj[idx].status = "UPLOADING";
            updateObj[idx].statusName = "上传中";
            this.setState({ fileList: updateObj })
        }
    }
    //删除上传的文件
    removeFile = (item) => {
        return () => {
            const { uploader, fileList } = this.state;
            uploader.removeFile(item.file)
            let idx = fileList.indexOf(item);
            fileList.splice(idx, 1);
            this.setState({ fileList })
        }
    }

    display = (item) => {
        return () => {
            this.setState({ showIframe: true })
        }
    }

    handleCancel = () => {
        this.setState({ showIframe: false })
    }

    render() {
        const { fileList, showIframe } = this.state
        console.log('showIframe', showIframe);

        return (
            <div className='webuploader'>
                <Card title="三维地形文件列表" className='audio-file-list'
                    extra={<div id="picker">选择大文件</div>}
                >
                    {
                        fileList.map((item, index) => {
                            return (
                                <Row key={nanoid()}>
                                    <Col span={8}>
                                        <p className='audio-file-list'>{item.file.name}</p>
                                    </Col>
                                    <Col span={6}>
                                        <Progress percent={item.progress === undefined ? '0' : item.progress} />
                                    </Col>
                                    <Divider type="vertical" />
                                    <Col span={3}>
                                        <Button type="dashed" onClick={this.up(item)}>开始上传</Button>
                                    </Col>
                                    <Divider type="vertical" />
                                    <Col span={2}>
                                        <Button type="dashed" onClick={this.removeFile(item)}>删除</Button>
                                    </Col>
                                    <Divider type="vertical" />
                                    <Col span={2}>
                                        <Button type="dashed" onClick={this.display(item)}>查看</Button>
                                    </Col>
                                </Row>
                            )
                        })
                    }
                </Card >
                <Modal width={'90%'} className='modal' title="现场建模" visible={showIframe} footer={null} onCancel={this.handleCancel}>
                    <iframe className='iframe' id='iframe' title='三维地形' src="http://fex.baidu.com/webuploader/document.html"></iframe>
                </Modal>
            </div>
        )
    }
}

代码中使用jquery,先安装 

    npm install jquery --save

removeFile

  • removeFile( file, true ) ⇒ undefined  移除某一文件, 默认只会标记文件状态为已取消,如果第二个参数为 true 则会从 queue 中移除。

如果需要删除文件,代码如下:

$("#removeFile").click(function () {
    console.log('bf files',uploader.getFiles())
    uploader.removeFile(file,true);
    console.log('af files',uploader.getFiles())
});

注:在操作的时候你会发现 删除前后files文件列表 一样,其实只不过是记录存在而已,已经从queue删除了。此时,点击上传删除的文件已经没响应。

注意

(*)webuploader中需要使用let that = this 先暂存component对象 然后webuploader register  upload等方法里面 this指代webuploader对象。

(*)不可以直接修改file对象 

3.修改webuploader UI 

        WebUploader只包含文件上传的底层实现,不包括UI部分。所以交互方面可以自由发挥。

4.参考资料

在React中使用WebUploader实现大文件分片上传的踩坑日记! - 杰哥斯坦森 - 博客园   函数式组件中使用WebUploader

文档 - Web Uploader 官网

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fang·up·ad

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值