12-23-上传master

This commit is contained in:
xingsy
2020-12-23 11:14:35 +08:00
parent 9769f83bc8
commit b42e0c1ddd
553 changed files with 56506 additions and 0 deletions

342
src/components/Upload/react-resumable.js vendored Normal file
View File

@ -0,0 +1,342 @@
import React from "react";
import { Table, Tag, Space, Progress, Button, Row, Col, Modal } from 'antd';
import { PauseOutlined, DeleteOutlined, CaretRightOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
import Resumablejs from "./resumable";
import './style.css';
/**
* 大文件上传组件
*/
export default class ReactResumableJs extends React.Component {
constructor(props) {
super(props);
this.state = {
fileList: [],
isPaused: false,
isUploading: false,
isSupported: false,
};
this.resumable = null;
}
componentDidMount = () => {
// 实例化上传组件( 用的是开源组件 resumablejs )
let _resumableField = this.__createResumbleObj();
// 当前浏览器是否支持 H5 Api
this.setState({ isSupported: _resumableField.support });
// 绑定上传组件, 拖拽组件
_resumableField.assignBrowse(this.uploader);
_resumableField.assignDrop(this.dropZone);
/* 注册新增文件通知 */
_resumableField.on('fileAdded', this.__fileAddedListener.bind(this));
/* 注册上传处理中文件通知 */
_resumableField.on('fileProgress', this.__fileProgressListener.bind(this));
/** 文件上传完成 */
_resumableField.on('fileSuccess', this.__fileSuccessListener.bind(this));
/** 文件上传失败 */
_resumableField.on('fileError', this.__fileErrorListener.bind(this));
this.resumable = _resumableField;
};
render() {
const columns = [
{
title: '文件名称',
dataIndex: 'filename',
key: 'filename',
render: text => <b>{text}</b>,
},
{
title: '上传进度',
dataIndex: 'prograss',
key: 'prograss',
responsive: ['lg'],
render: (val, record) => <Progress percent={val} status={ record.error ? "exception" : "active"} />,
},
{
title: '动作',
dataIndex: 'action',
key: 'action',
width: '30%',
responsive: ['md'],
render: (text, record) => (
<Space size="middle">
<Button type="dashed" style={{display: !record.pause && !record.complete && !record.error ? '' : 'none'}} icon={<PauseOutlined/>} onClick={() => this.__uploadPause(record.filename)}>暂停上传</Button>
<Button type="dashed" style={{display: record.pause && !record.complete && !record.error ? '' : 'none'}} icon={<CaretRightOutlined/>} onClick={() => this.__uploadResum(record.filename)}>恢复上传</Button>
<Button type="danger" style={{display: record.pause || record.complete || record.error ? '' : 'none'}} icon={<DeleteOutlined/>} onClick={() => this.__removeFile(record.filename)}>移除文件</Button>
</Space>
),
},
];
return (
<>
<Row>
<Col span={24}>
<div id={this.props.dropTargetID} ref={node => this.dropZone = node}>
<div className="resumable-error" style={{display: this.state.isSupported ? 'none' : ''}}>
Your browser, unfortunately, is not supported by Resumable.js. The library requires support for <a href="http://www.w3.org/TR/FileAPI/">the HTML5 File API</a> along with <a href="http://www.w3.org/TR/FileAPI/#normalization-of-params">file slicing</a>.
</div>
<div className="resumable-drop" style={{display: this.state.isSupported ? '' : 'none'}}>
文件拖拽到该区域或者
<a className="resumable-browse"
ref={node=> {this.uploader = node; this.dropZone = node;}}
type="file"
id={this.props.uploaderID}
className='btn'
name={this.props.uploaderID + '-upload'}
accept={this.props.fileAccept || '*'}
disabled={this.props.disableInput || false}><u>点击连接添加文件</u></a>
</div>
</div>
</Col>
</Row>
<Row>
<Col span={24}>
<Table columns={columns} dataSource={[...this.state.fileList]} pagination={false} bordered/>
</Col>
</Row>
</>
);
}
/**
* 实例化上传组件
*/
__createResumbleObj() {
return new Resumablejs({
target: this.props.service,
query: this.props.query,// 自定义参数
forceChunkSize: true,// 是否严格执行分片
fileType: this.props.filetypes,
maxFiles: this.props.maxFiles,
maxFileSize: this.props.maxFileSize,
headers: this.props.headerObject || {},
chunkSize: this.props.chunkSize,
testChunks: false,// 不启用测试块
simultaneousUploads: this.props.simultaneousUploads,
fileParameterName: this.props.fileParameterName,
forceChunkSize: true,// 是否严格执行分片
maxChunkRetries: 10,// 最大重试次数
chunkRetryInterval: 1000,// 重试间隔时间 10 秒
throttleProgressCallbacks: 1,// 上传进度播报周期 (1秒)
forceChunkSize: this.props.forceChunkSize
});
}
/**
* 添加文件时的监听
*
* @param {*} file
*/
__fileAddedListener(file) {
// 更新文件队列表单
let _cache = this.state.fileList;
_cache.push({
key: _cache.length + 1,
filename: file.fileName,
uploading: true,
prograss: Math.floor(file.progress()*100),
});
// 更新组件状态,进行组件重绘
this.setState({ fileList: _cache });
if (typeof this.props.onFileAdded === "function") {
this.props.onFileAdded(file, this.resumable);
} else {
this.resumable.upload();
}
}
/**
* 文件上传进度播报
* @param {*} file
*/
__fileProgressListener(file) {
// 更新文件队列表单
let _cache = this.state.fileList;
let matchedObj = _cache.find((obj) => obj.filename === file.fileName);
if(matchedObj) {
matchedObj.prograss = Math.floor(file.progress()*100);
// 更新组件状态,进行组件重绘
this.setState({ fileList: _cache });
}
}
/**
* 文件上传完成
* @param {*} file
*/
__fileSuccessListener(file) {
// 更新文件队列表单
let _cache = this.state.fileList;
let matchedObj = _cache.find((obj) => obj.filename === file.fileName);
if(matchedObj) {
matchedObj.complete = true;
// 更新组件状态,进行组件重绘
this.setState({ fileList: _cache });
}
if (typeof this.props.onUploadSuccess === "function") {
this.props.onUploadSuccess(file, this.resumable);
}
}
/**
* 文件上传失败
* @param {*} file
*/
__fileErrorListener(file) {
// 更新文件队列表单
let _cache = this.state.fileList;
let matchedObj = _cache.find((obj) => obj.filename === file.fileName);
if(matchedObj) {
matchedObj.error = true;
// 更新组件状态,进行组件重绘
this.setState({ fileList: _cache });
}
if (typeof this.props.onUploadError === "function") {
this.props.onUploadError(file, this.resumable);
}
}
/**
* 移除上传列表中的文件
*/
__removeFile(filename) {
/** 查询当前文件 */
const file = this.resumable.files.find(obj => obj.file.name === filename);
const selfRef = this;
if(!file.isComplete()) {
const { confirm } = Modal;
confirm({
title: '确定要移除当前任务吗?',
icon: <ExclamationCircleOutlined />,
content: '当前上传任务尚未完成,移除后将无法恢复,确定要执行该操作吗?',
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk() {// 取消选中文件的上传操作
file.cancel();
selfRef.__handleRemoveFile(filename);
},
});
} else {
selfRef.__handleRemoveFile(filename);
}
}
__handleRemoveFile(filename) {
// 更新文件队列表单
let _cache= this.state.fileList;
// 移除指定的元素
_cache.splice(_cache.findIndex((obj) => obj.filename === filename), 1)
// 修改上传列表状态
this.setState({ fileList: _cache });
}
/**
* 暂停上传
*/
__uploadPause(filename) {
// 取消选中文件的上传操作
this.resumable.files.find(obj => obj.file.name === filename)._pause = true;
// 更新文件队列表单
let _cache = this.state.fileList;
let matchedObj = _cache.find((obj) => obj.filename === filename);
if(matchedObj) {
matchedObj.pause = true;
// 更新组件状态,进行组件重绘
this.setState({ fileList: _cache });
}
}
/**
* 恢复上传
*/
__uploadResum(filename) {
let file = this.resumable.files.find(obj => obj.file.name === filename);
// 取消暂停状态
file._pause = false;
// 取消选中文件的上传操作
file.upload();
// 更新文件队列表单
let _cache = this.state.fileList;
let matchedObj = _cache.find((obj) => obj.filename === filename);
if(matchedObj) {
delete matchedObj.pause;
// 更新组件状态,进行组件重绘
this.setState({ fileList: _cache });
}
}
}
/**
* 对外暴露的属性值
*/
ReactResumableJs.defaultProps = {
maxFiles: 10,// 添加最大文件数
uploaderID: 'default-resumable-uploader',
dropTargetID: 'dropTarget',
query: {},
filetypes: [],// 文件扩展名
fileAccept: '*',// 文件头类型
maxFileSize: 1204 * 1024 * 1024 * 1024,// max size 1T
onUploadErrorCallback: (file, errorCount) => {
console.log('error', file, errorCount);
},
onFileRemoved: function (file) {
return file;
},
onCancelUpload: function () {
return true;
},
onPauseUpload: function () {
return true;
},
onResumeUpload: function () {
return true;
},
onStartUpload: function () {
return true;
},
onUploadSuccess: function() {
return true;
},
onUploadError: function() {
return true;
},
disableDragAndDrop: false,// 允许拖拽操作
chunkSize: 5 * 1024 * 1024,// 每个分批那的尺寸 5M
simultaneousUploads: 5,// 同步上传的分片数
fileParameterName: 'file',
generateUniqueIdentifier: null,
maxFilesErrorCallback: null,
cancelButton: false,
pause: false,
startButton: null,
pauseButton: null,
previousText: "",
headerObject : {},
forceChunkSize: false
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
/* Uploader: Drag & Drop */
.resumable-error {font-size:14px; font-style:italic;}
.resumable-drop {padding:55px 15px; font-size:18px; text-align:center; color:#666; font-weight:bold;background-color:#eee; border:2px dashed #aaa; border-radius:10px; margin-top:40px; z-index:9999;}
.dragover {padding:30px; color:#555; background-color:#ddd; border:1px solid #999;}
/* Uploader: Progress bar */
.resumable-progress {margin:30px 0 30px 0; width:100%;}
.progress-container {height:7px; background:#9CBD94; position:relative; }
.progress-bar {position:absolute; top:0; left:0; bottom:0; background:#45913A; width:0;}
.progress-text {font-size:11px; line-height:9px; padding-left:10px;}
.progress-pause {padding:0 0 0 7px;}
.progress-resume-link {display:none;}
.is-paused .progress-resume-link {display:inline;}
.is-paused .progress-pause-link {display:none;}
.is-complete .progress-pause {display:none;}
/* Uploader: List of items being uploaded */
.resumable-list {overflow:auto; margin-right:-20px;}
.uploader-item {width:148px; height:90px; background-color:#666; position:relative; border:2px solid black; float:left; margin:0 6px 6px 0;}
.uploader-item-thumbnail {width:100%; height:100%; position:absolute; top:0; left:0;}
.uploader-item img.uploader-item-thumbnail {opacity:0;}
.uploader-item-creating-thumbnail {padding:0 5px; font-size:9px; color:white;}
.uploader-item-title {position:absolute; font-size:9px; line-height:11px; padding:3px 50px 3px 5px; bottom:0; left:0; right:0; color:white; background-color:rgba(0,0,0,0.6); min-height:27px;}
.uploader-item-status {position:absolute; bottom:3px; right:3px;}
/* Uploader: Hover & Active status */
.uploader-item:hover, .is-active .uploader-item {border-color:#4a873c; cursor:pointer; }
.uploader-item:hover .uploader-item-title, .is-active .uploader-item .uploader-item-title {background-color:rgba(74,135,60,0.8);}
/* Uploader: Error status */
.is-error .uploader-item:hover, .is-active.is-error .uploader-item {border-color:#900;}
.is-error .uploader-item:hover .uploader-item-title, .is-active.is-error .uploader-item .uploader-item-title {background-color:rgba(153,0,0,0.6);}
.is-error .uploader-item-creating-thumbnail {display:none;}