美文网首页
实现上传下载进度条和取消ajax请求

实现上传下载进度条和取消ajax请求

作者: ThemisHoo | 来源:发表于2019-10-15 20:01 被阅读0次

一、实现功能点:

1.传输文件进度条展示
2.传输过程中可取消
3.实现多文件上传下载进度展示

二、知识点:

axios的config中封装了onDownloadProgress(下载进度),onUploadProgress(上传进度),cancelToken(取消请求)的方法

1、onDownloadProgress为下载进度方法,在下载文件时被实时调用,返回的progress.loaded为已经下载的文件大小,total在下载时拿不到,只能通过下载前获取文件大小。
注:测试过程中发现,如果下载文件过小,如几十K,onDownloadProgress 不会被调用。此时下载速度非常快,可以在then和catch方法中直接处理进度
 axios({
   url: 'xxx',
   method: 'get',
   onDownloadProgress (progress) {
     console.log(Math.round(progress.loaded / total * 100) + '%');
   }
 })
2、onUploadProgress为上传进度的方法,在上传文件时被实时调用,返回的progress.loaded为已经上传的文件大小,progress.total为总文件大小。
注:在下载请求中,也会调用一次onUploadProgress方法。
axios({
   url: 'xxx',
   method: 'post',
   onDownloadProgress (progress) {
     console.log(Math.round(progress.loaded / progress.total * 100) + '%');
   }
 })
3、cancelToken为取消请求方法,每个请求有唯一token,多个请求同时存在时,可以通过token区分关闭哪个请求。

有两种调用方式,我使用的是第二种

方法一
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('/url', {
  cancelToken: source.token
}).catch(function (thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.murlessage);
  } else {
    // handle error
  }
});

axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token
})

// 取消请求时调用此方法
source.cancel('Operation canceled by the user.');
方法二
const CancelToken = axios.CancelToken;
let cancel;

axios.get('/url', {
  cancelToken: new CancelToken(function executor(c) {
    // An executor function receives a cancel function as a parameter
    cancel = c;
  })
});

// 取消请求时调用方法
cancel();

三、完整代码(可忽略)

主要记录多个上传下载,对cancelToken和页面显示的处理逻辑,只要了解上传下载和取消请求的原理即可,此部分可忽略。

import React, { Component } from 'react';
import axios from 'axios';

const CancelToken = axios.CancelToken;
// 创建一个数组,存放所有请求的cancelToken的对象
let cancelList = []

export default class BaseCompnent extends Component {
    state = {};
  
    // 取消请求时调用的方法
    cancelAllAjax = () => {
        cancelList.map(e => {
             // 执行每个取消请求方法
            e()
        })
    }
    // 存放所有的请求句柄
    request = {
        get: (url, params, options) => {},
        post: (url, params, options) => {
            return axios.post(url, params, {
                cancelToken: new CancelToken((c) => {
                    //   将所有请求push到cancelList中
                    cancelList.push(c)
                }),
                ...options,
                headers: (Object.assign({}, (options || {}).headers || {}, {'X-Requested-With': 'XMLHttpRequest', 'returnurl': returnUrl, 'token': token})),
            }).then(this.resolveFilter, this.rejectFilter);
        },
        postTest: (url, params, options) => {},
        del: (url, params, options) => {};

    componentWillUnmount() {
        // 组件卸载之后,打断所有未结束得请求,
        // 子类要是要使用componentWillUnmount,需要显示的调用super.componentWillUnmount();
        this.cancelAllAjax()
    }
}

import React, { Component } from 'react';
import { BaseComponent } from 'components';

import { Button, message, Modal, Row, Col, Select, Progress } from 'antd';
const Option = Select.Option;

export default class Operation extends BaseComponent {
    constructor(props) {
        super(props);
        this.state = {
            visibleLoad: false, // 上传下载进度条模态框
            loadList: [], // 进度条列表
            textLoad: true, // 上传下载进度title
        }
    }

    componentWillMount() {}

    componentDidMount() {}

    // 下载文件流接口
    getFileStrem = (fileName, iconType, fileSize, markType) => {
        let { loadList } = this.state
        loadList.push({
            fileName: fileName,
            percent: 0,
            uid: fileName, // 这里最好不要用文件名做唯一标识,我懒~
            status: 'active'
        })
        this.setState({
            visibleLoad: true,
            textLoad: false
        })

        this.request.post('/proxy/file/download',  {
            responseType: 'blob',
            // 处理下载文件进度
            onDownloadProgress : progressEvent => {
                let percent = progressEvent.loaded / fileSize * 100 | 0
                let { loadList } = this.state
                // 将每个进度push到loadList中,用于页面展示
                loadList.forEach((ele, idex) => {
                    if (ele.uid == fileName) {
                        let lc = {
                            fileName: fileName,
                            percent: percent,
                            uid: fileName,
                            status: 'active'
                        }
                        loadList[idex] = lc
                        this.setState({
                            loadList
                        })
                    }
                })
            },
        }).then((res) => {}).catch((err) => {});
    }

    // 上传文件
    uploadFile = (MultipartFile, type, markType) => {
        let { loadList } = this.state
        loadList.push({
            fileName: MultipartFile.name,
            percent: 0,
            uid: MultipartFile.uid, // 上传文件可以直接拿到文件的uid,这里直接使用
            status: 'active'
        })
        this.setState({
            visibleLoad: true,
            textLoad: true
        })
        var formData = new FormData()
        formData.append('fileData', MultipartFile, MultipartFile.name)
        this.request.post('/proxy/file/upload', formData, {
            headers: {
                'Content-Type': 'multipart/form-data',
            },
            // 处理上传进度
            onUploadProgress: progressEvent => {
                let percent = progressEvent.loaded / progressEvent.total * 100 | 0
                let { loadList } = this.state
                // 将每个上传进度push进 loadList,用于页面展示
                loadList.forEach((ele, idex) => {
                    if (ele.uid == MultipartFile.uid) {
                        let lc = {
                            fileName: MultipartFile.name,
                            percent: percent,
                            uid: MultipartFile.uid,
                            status: percent === 100 ? 'success' : 'active'
                        }
                        loadList[idex] = lc
                        this.setState({
                            loadList
                        })
                    }
                })
            }
        }).then(res => {}).catch(err => {});
    }

  handleCancelLoad = () => {
        this.setState({
            visibleLoad: false,
            loadList: []
        })
        // 取消所有请求
        this.cancelAllAjax()
    }
  
    render() {
        const {visibleLoad, loadList, textLoad} = this.state    
        return (
            <div className="process-content operation-content">
                            <Modal
                                title={textLoad ? '正在上传' : '正在下载'}
                                visible={visibleLoad}
                                footer={null}
                                onCancel={this.handleCancelLoad}
                                >
                                {
                                    loadList.length && loadList.map((ele, index) => {
                                        return <Row key={index}>
                                            <Col span={5}>{ele.fileName.length <= 21 ? ele.fileName : `${ele.fileName.substring(0, 5)}...${ele.fileName.substring(ele.fileName.length-16,ele.fileName.length)}`}</Col>
                                            <Col span={19}><Progress percent={ele.percent} status={ele.status}/></Col>
                                        </Row>
                                    })
                                }
                                <Row style={{borderTop: '1px solid #dddee3', paddingTop: '20px'}}><Col span={2} offset={22}>
                                    <Button onClick={this.handleCancelLoad}>{textLoad ? '取消上传' : '取消下载'}</Button>
                                </Col></Row>
                            </Modal>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

相关文章

  • 实现上传下载进度条和取消ajax请求

    一、实现功能点: 1.传输文件进度条展示2.传输过程中可取消3.实现多文件上传下载进度展示 二、知识点: axio...

  • 取消ajax请求

    取消异步请求 原生XHR 调用调用XHR对象的.abort()方法 jquery ajax axios 特点可以同...

  • 【React】应用->顶部进度条

    React 顶部进度条 瞎扯 在做Ajax 请求,或者请求相关资源的时候, 需要有一个进度条来让页面看起来更加的自...

  • 上传下载图片,django-filter

    上传下载图片 上传图片 下载图片 django-filter 进行信息过滤 流程:html的ajax请求-->vi...

  • Ajax异步请求[17.7.10]

    Ajax异步请求 Ajax全称为Asynchronous Javascript and XML。通过Ajax实现了...

  • Ajax的步骤及其原理

    ajax是实现前端异步请求非常重要的方法。 下面列出ajax的全部参数 Ajax原理和XmlHttpRequest...

  • ajax

    定义和用法: ajax() 方法通过 HTTP 请求加载远程数据。 该方法是 jQuery 底层 AJAX 实现。...

  • 学习规划

    这是一个关于对javascript主题学习的工程 主题一:ajax 原生xhr对象 跨域处理 ajax请求进度条 ...

  • 前端ajax实现和跨域实现

    下面是用chrome实现ajax请求,并对ajax中get和post请求进行封装,最后对跨域请求的前端处理本文用的...

  • AJAX POST请求实现/AJAX封装/node/RESTfu

    AJAX POST请求实现 AJAX封装 JSONP node.js 扩展

网友评论

      本文标题:实现上传下载进度条和取消ajax请求

      本文链接:https://www.haomeiwen.com/subject/sqbjmctx.html