react-fileupload的安装
使用npm install react-fileupload --save
或 yarn react-fileupload
安装均可
使用方法
若在开发时用的是react@15.x的版本,直接引入一下代码即可使用
const FileUpload = require('react-fileupload');
...
render(){
/*set properties*/
const options={
baseUrl:'http://127.0.0.1',
param:{
fid:0
}
}
/*Use FileUpload with options*/
/*Set two dom with ref*/
return (
<FileUpload options={
options}>
<button ref="chooseBtn">choose</button>
<button ref="uploadBtn">upload</button>
</FileUpload>
)
}
但此代码并不适用于react@16.x的版本
属性值
react-fileupload的属性有很多,这里只对常用的属性进行介绍,其余属性详见github官网
- baseUrl:图片上传后提交的目标地址
- fileFieldName:为此类提交的图片起一个键名作为标识符
- dataType:回应的格式
- chooseAndUpload:是否在选择图片时自动提交
- uploadSuccess:成功提交后的回调函数
- uploadError:未能成功提交的回调函数
要注意的是,在chooseAndUpload属性为true的时候,提交按钮的ref
值需要改成chooseAndUpload
以下是代码案例
import React, {
Component } from 'react'
// 这里引入的是本地文件而不是下载的模块,是为了适配React@16.x的版本,这一块在后面会讲到
import FileUpload from './react-fileupload.jsx'
class FileUploader extends Component {
constructor(props) {
super(props)
this.state = {
}
}
render() {
/*set properties*/
const options={
baseUrl: '/manage/product/upload.do',
fileFieldName: 'upload_file',
dataType: 'json',
chooseAndUpload:true,
uploadSuccess: (res)=>{
this.props.onSuccess(res.data)
},
uploadError: (err)=>{
this.props.onError(err.message||'上传失败')
}
}
/*Use FileUpload with options*/
/*Set two dom with ref*/
return (
<FileUpload options={
options}>
<button className="btn btn-xs btn-default" ref="chooseAndUpload">请选择图片</button>
</FileUpload>
)
}
}
React@16.x的版本兼容
在上面提到,react-fileupload是基于react@15.x的版本开发的,而react的一大特点就是新版本对旧版本不兼容,这里给出在react@16.x版本下使用react-fileupload的方法
由于源代码就已经不兼容react@16.x,因此我们需要将源代码取出进行改写,首先找到node_modules里面react-fileupload的源码文件,即下图中的FileUpload.js
将FileUpload.js中的内容复制出来,并存放到本地目录的文件中,然后开始改写
这里我先给出我改好后的文件,直接复制到本地文件后引入即可使用,具体修改方法放到代码后面,需要安装prop-types,安装方法直接使用npm install prop-types --save
或 yarn add prop-types
即可
import React from 'react'
import PT from 'prop-types';
const emptyFunction = function() {
}
/*当前IE上传组的id*/
let currentIEID = 0
/*存放当前IE上传组的可用情况*/
const IEFormGroup = [true]
/*当前xhr的数组(仅有已开始上传之后的xhr)*/
let xhrList = []
let currentXHRID = 0
class FileUpload extends React.Component{
constructor(props){
super(props);
this.state={
chooseBtn: {
}, //选择按钮。如果chooseAndUpload=true代表选择并上传。
uploadBtn: {
}, //上传按钮。如果chooseAndUpload=true则无效。
before: [], //存放props.children中位于chooseBtn前的元素
middle: [], //存放props.children中位于chooseBtn后,uploadBtn前的元素
after: []
}
}
/*根据props更新组件*/
_updateProps(props) {
this.isIE = !(this.checkIE() < 0 || this.checkIE() >= 10)
const options = props.options
this.baseUrl = options.baseUrl //域名
this.param = options.param //get参数
this.chooseAndUpload = options.chooseAndUpload || false //是否在用户选择了文件之后立刻上传
this.paramAddToField = options.paramAddToField || undefined //需要添加到FormData的对象。不支持IE
/*upload success 返回resp的格式*/
this.dataType = 'json'
options.dataType && (options.dataType.toLowerCase() == 'text') && (this.dataType = 'text')
this.wrapperDisplay = options.wrapperDisplay || 'inline-block' //包裹chooseBtn或uploadBtn的div的display
this.timeout = (typeof options.timeout == 'number' && options.timeout > 0) ? options.timeout : 0 //超时时间
this.accept = options.accept || '' //限制文件后缀
this.multiple = options.multiple || false
this.numberLimit = options.numberLimit || false //允许多文件上传时,选择文件数量的限制
this.fileFieldName = options.fileFieldName || false //文件附加到formData上时的key,传入string指定一个file的属性名,值为其属性的值。不支持IE
this.withCredentials = options.withCredentials || false //跨域时是否使用认证信息
this.requestHeaders = options.requestHeaders || false //要设置的请求头键值对
/*生命周期函数*/
/**
* beforeChoose() : 用户选择之前执行,返回true继续,false阻止用户选择
* @param null
* @return {boolean} 是否允许用户进行选择
*/
this.beforeChoose = options.beforeChoose || emptyFunction
/**
* chooseFile(file) : 用户选择文件后的触发的回调函数
* @param file {File | string} 现代浏览器返回File对象,IE返回文件名
* @return
*/
this.chooseFile = options.chooseFile || emptyFunction
/**
* beforeUpload(file,mill) : 用户上传之前执行,返回true继续,false阻止用户选择
* @param file {File | string} 现代浏览器返回File对象,IE返回文件名
* @param mill {long} 毫秒数,如果File对象已有毫秒数则返回一样的
* @return {boolean || object} 是否允许用户进行上传 (hack:如果是obj{
* assign:boolean 默认true
* param:object
* }), 则对本次的param进行处理
*/
this.beforeUpload = options.beforeUpload || emptyFunction
/**
* doUpload(file,mill) : 上传动作(xhr send | form submit)执行后调用
* @param file {File | string} 现代浏览器返回File对象,IE返回文件名
* @param mill {long} 毫秒数,如果File对象已有毫秒数则返回一样的
* @return
*/
this.doUpload = options.doUpload || emptyFunction
/**
* uploading(progress) : 在文件上传中的时候,浏览器会不断触发此函数。IE中使用每200ms触发的假进度
* @param progress {Progress} progress对象,里面存有例如上传进度loaded和文件大小total等属性
* @return
*/
this.uploading = options.uploading || emptyFunction
/**
* uploadSuccess(resp) : 上传成功后执行的回调(针对AJAX而言)
* @param resp {json | string} 根据options.dataType指定返回数据的格式
* @return
*/
this.uploadSuccess = options.uploadSuccess || emptyFunction
/**
* uploadError(err) : 上传错误后执行的回调(针对AJAX而言)
* @param err {Error | object} 如果返回catch到的error,其具有type和message属性
* @return
*/
this.uploadError = options.uploadError || emptyFunction
/**
* uploadFail(resp) : 上传失败后执行的回调(针对AJAX而言)
* @param resp {string} 失败信息
*/
this.uploadFail = options.uploadFail || emptyFunction
/**
* onabort(mill, xhrID) : 主动取消xhr进程的响应
* @param mill {long} 毫秒数,本次上传时刻的时间
* @param xhrID {int} 在doUpload时会返回的当次xhr代表ID
*/
this.onabort = options.onabort || emptyFunction
this.files = options.files || this.files || false //保存需要上传的文件
/*特殊内容*/
/*IE情况下,由于上传按钮被隐藏的input覆盖,不能进行disabled按钮处理。
* 所以当disabledIEChoose为true(或者func返回值为true)时,禁止IE上传。
*/
this.disabledIEChoose = options.disabledIEChoose || false
this._withoutFileUpload = options._withoutFileUpload || false //不带文件上传,为了给秒传功能使用,不影响IE
this.filesToUpload = options.filesToUpload || [] //使用filesToUpload()方法代替
this.textBeforeFiles = options.textBeforeFiles || false //make this true to add text fields before file data
/*使用filesToUpload()方法代替*/
if (this.filesToUpload.length && !this.isIE) {
this.filesToUpload.forEach( file => {
this.files = [file]
this.commonUpload()
})
}
/*放置虚拟DOM*/
let chooseBtn, uploadBtn, flag = 0
const before = [], middle = [], after = []
if (this.chooseAndUpload) {
React.Children.forEach(props.children, (child)=> {
if (child && child.ref <