React圖片上傳元件react-fileupload的使用方法
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 == 'chooseAndUpload') {
chooseBtn = child
flag++
} else {
flag == 0 ? before.push(child) : flag == 1 ? middle.push(child) : ''
}
})
} else {
React.Children.forEach(props.children, (child)=> {
if (child && child.ref == 'chooseBtn') {
chooseBtn = child
flag++
} else if (child && child.ref == 'uploadBtn') {
uploadBtn = child
flag++
} else {
flag == 0 ? before.push(child) : flag == 1 ? middle.push(child) : after.push(child)
}
})
}
this.setState({
chooseBtn,
uploadBtn,
before,
middle,
after
})
}
/*觸發隱藏的input框選擇*/
/*觸發beforeChoose*/
commonChooseFile() {
const jud = this.beforeChoose()
if (jud != true && jud != undefined) return
this.refs['ajax_upload_file_input'].click()
}
/*現代瀏覽器input change事件。File API儲存檔案*/
/*觸發chooseFile*/
commonChange(e) {
let files
e.dataTransfer ? files = e.dataTransfer.files :
e.target ? files = e.target.files : ''
/*如果限制了多檔案上傳時的數量*/
const numberLimit = typeof this.numberLimit === 'function' ? this.numberLimit() : this.numberLimit
if(this.multiple && numberLimit && files.length > numberLimit) {
const newFiles = {}
for(let i = 0; i< numberLimit; i++) newFiles[i] = files[i]
newFiles.length = numberLimit
files = newFiles
}
this.files = files
this.chooseFile(files)
this.chooseAndUpload && this.commonUpload()
}
/*執行上傳*/
commonUpload() {
/*mill引數是當前時刻毫秒數,file第一次進行上傳時會新增為file的屬性,也可在beforeUpload為其新增,之後同一檔案的mill不會更改,作為檔案的識別id*/
const mill = (this.files.length && this.files[0].mill) || (new Date).getTime()
const jud = this.beforeUpload(this.files, mill)
if (jud != true && jud != undefined && typeof jud != 'object') {
/*清除input的值*/
this.refs['ajax_upload_file_input'].value = ''
return
}
if (!this.files) return
if (!this.baseUrl) throw new Error('baseUrl missing in options')
/*用於存放當前作用域的東西*/
const scope = {}
/*組裝FormData*/
let formData = new FormData()
/*If we need to add fields before file data append here*/
if(this.textBeforeFiles){
formData = this.appendFieldsToFormData(formData);
}
if (!this._withoutFileUpload) {
const fieldNameType = typeof this.fileFieldName
/*判斷是用什麼方式作為formdata item 的 name*/
Object.keys(this.files).forEach(key => {
if(key == 'length') return
if(fieldNameType == 'function') {
const file = this.files[key]
const fileFieldName = this.fileFieldName(file)
formData.append(fileFieldName, file)
}else if(fieldNameType == 'string') {
const file = this.files[key]
formData.append(this.fileFieldName, file)
}else {
const file = this.files[key]
formData.append(file.name, file)
}
})
}
/*If we need to add fields after file data append here*/
if(!this.textBeforeFiles){
formData = this.appendFieldsToFormData(formData);
}
const baseUrl = this.baseUrl
/*url引數*/
/*如果param是一個函式*/
const param = typeof this.param === 'function' ? this.param(this.files) : this.param
let paramStr = ''
if (param) {
const paramArr = []
param['_'] = mill
Object.keys(param).forEach(key =>
paramArr.push(`${key}=${param[key]}`)
)
paramStr = '?' + paramArr.join('&')
}
const targeturl = baseUrl + paramStr
/*AJAX上傳部分*/
const xhr = new XMLHttpRequest()
xhr.open('POST', targeturl, true)
/*跨域是否開啟驗證資訊*/
xhr.withCredentials = this.withCredentials
/*是否需要設定請求頭*/
const rh = this.requestHeaders
rh && Object.keys(rh).forEach(key =>
xhr.setRequestHeader(key, rh[key])
)
/*處理超時。用定時器判斷超時,不然xhr state=4 catch的錯誤無法判斷是超時*/
if(this.timeout) {
xhr.timeout = this.timeout
xhr.ontimeout = () => {
this.uploadError({type: 'TIMEOUTERROR', message: 'timeout'})
scope.isTimeout = false
}
scope.isTimeout = false
setTimeout(()=>{
scope.isTimeout = true
},this.timeout)
}
xhr.onreadystatechange = () => {
/*xhr finish*/
try {
if (xhr.readyState == 4 && xhr.status >= 200 && xhr.status < 400) {
const resp = this.dataType == 'json' ? JSON.parse(xhr.responseText) : xhr.responseText
this.uploadSuccess(resp)
} else if (xhr.readyState == 4) {
/*xhr fail*/
const resp = this.dataType == 'json' ? JSON.parse(xhr.responseText) : xhr.responseText
this.uploadFail(resp)
}
} catch (e) {
/*超時丟擲不一樣的錯誤,不在這裡處理*/
!scope.isTimeout && this.uploadError({type: 'FINISHERROR', message: e.message})
}
}
/*xhr error*/
xhr.onerror = () => {
try {
const resp = this.dataType == 'json' ? JSON.parse(xhr.responseText) : xhr.responseText
this.uploadError({type: 'XHRERROR', message: resp})
} catch (e) {
this.uploadError({type: 'XHRERROR', message: e.message})
}
}
/*這裡部分瀏覽器實現不一致,而且IE沒有這個方法*/
xhr.onprogress = xhr.upload.onprogress = progress => {
this.uploading(progress, mill)
}
/*不帶檔案上傳,給秒傳使用*/
this._withoutFileUpload ? xhr.send(null) : xhr.send(formData)
/*儲存xhr id*/
xhrList.push(xhr)
const cID = xhrList.length - 1
currentXHRID = cID
/*有響應abort的情況*/
xhr.onabort = () => this.onabort(mill, cID)
/*trigger執行上傳的使用者回撥*/
this.doUpload(this.files, mill, currentXHRID)
/*清除input的值*/
this.refs['ajax_upload_file_input'].value = ''
}
/*組裝自定義新增到FormData的物件*/
appendFieldsToFormData(formData){
const field = typeof this.paramAddToField == 'function' ? this.paramAddToField() : this.paramAddToField
field &&
Object.keys(field).map(index=>
formData.append(index, field[index])
)
return formData
}
/*iE選擇前驗證*/
/*觸發beforeChoose*/
IEBeforeChoose(e) {
const jud = this.beforeChoose()
jud != true && jud != undefined && e.preventDefault()
}
/*IE需要使用者真實點選上傳按鈕,所以使用透明按鈕*/
/*觸發chooseFile*/
IEChooseFile(e) {
this.fileName = e.target.value.substring(e.target.value.lastIndexOf('\\') + 1)
this.chooseFile(this.fileName)
/*先執行IEUpload,配置好action等引數,然後submit*/
this.chooseAndUpload && (this.IEUpload() !== false) &&
document.getElementById(`ajax_upload_file_form_${this.IETag}${currentIEID}`).submit()
e.target.blur()
}
/*IE處理上傳函式*/
/*觸發beforeUpload doUpload*/
IEUpload(e) {
const mill = (new Date).getTime()
const jud = this.beforeUpload(this.fileName, mill)
if(!this.fileName || (jud != true && jud != undefined) ) {
e && e.preventDefault()
return false
}
const that = this
/*url引數*/
const baseUrl = this.baseUrl
const param = typeof this.param === 'function' ? this.param(this.fileName) : this.param
let paramStr = ''
if (param) {
const paramArr = []
param['_'] = mill
param['ie'] === undefined && (param['ie'] = 'true')
for (const key in param) {
if(param[key] != undefined) paramArr.push(`${key}=${param[key]}`)
}
paramStr = '?' + paramArr.join('&')
}
const targeturl = baseUrl + paramStr
document.getElementById(`ajax_upload_file_form_${this.IETag}${currentIEID}`).setAttribute('action', targeturl)
/*IE假的上傳進度*/
const getFakeProgress = this.fakeProgress()
let loaded = 0,
count = 0
const progressInterval = setInterval(() => {
loaded = getFakeProgress(loaded)
this.uploading({
loaded,
total: 100
},mill)
/*防止永久執行,設定最大的次數。暫時為30秒(200*150)*/
++count >= 150 && clearInterval(progressInterval)
},200)
/*當前上傳id*/
const partIEID = currentIEID
/*回撥函式*/
window.attachEvent ?
document.getElementById(`ajax_upload_file_frame_${this.IETag}${partIEID}`).attachEvent('onload', handleOnLoad) :
document.getElementById(`ajax_upload_file_frame_${this.IETag}${partIEID}`).addEventListener('load', handleOnLoad)
function handleOnLoad() {
/*clear progress interval*/
clearInterval(progressInterval)
try {
that.uploadSuccess(that.IECallback(that.dataType, partIEID))
} catch (e) {
that.uploadError(e)
} finally {
/*清除輸入框的值*/
const oInput = document.getElementById(`ajax_upload_hidden_input_${that.IETag}${partIEID}`)
oInput.outerHTML = oInput.outerHTML
}
}
this.doUpload(this.fileName, mill)
/*置為非空閒*/
IEFormGroup[currentIEID] = false
}
/*IE回撥函式*/
//TODO 處理Timeout
IECallback(dataType, frameId) {
/*回覆空閒狀態*/
IEFormGroup[frameId] = true
const frame = document.getElementById(`ajax_upload_file_frame_${this.IETag}${frameId}`)
const resp = {}
const content = frame.contentWindow ? frame.contentWindow.document.body : frame.contentDocument.document.body
if(!content) throw new Error('Your browser does not support async upload')
try {
resp.responseText = content.innerHTML || 'null innerHTML'
resp.json = JSON ? JSON.parse(resp.responseText) : eval(`(${resp.responseText})`)
} catch (e) {
/*如果是包含了<pre>*/
if (e.message && e.message.indexOf('Unexpected token') >= 0) {
/*包含返回的json*/
if (resp.responseText.indexOf('{') >= 0) {
const msg = resp.responseText.substring(resp.responseText.indexOf('{'), resp.responseText.lastIndexOf('}') + 1)
return JSON ? JSON.parse(msg) : eval(`(${msg})`)
}
return {type: 'FINISHERROR', message: e.message}
}
throw e
}
return dataType == 'json' ? resp.json : resp.responseText
}
/*外部呼叫方法,主動觸發選擇檔案(等同於呼叫btn.click()), 僅支援現代瀏覽器*/
forwardChoose() {
if(this.isIE) return false
this.commonChooseFile()
}
/**
* 外部呼叫方法,當多檔案上傳時,用這個方法主動刪除列表中某個檔案
* TODO: 此方法應為可以任意操作檔案陣列
* @param func 使用者呼叫時傳入的函式,函式接收引數files(filesAPI 物件)
* @return Obj File API 物件
* File API Obj:
* {
* 0 : file,
* 1 : file,
* length : 2
* }
*/
fowardRemoveFile(func) {
this.files = func(this.files)
}
/*外部呼叫方法,傳入files(File API)物件可以立刻執行上傳動作,IE不支援。呼叫隨後會觸發beforeUpload*/
filesToUpload(files) {
if(this.isIE) return
this.files = files
this.commonUpload()
}
/*外部呼叫方法,取消一個正在進行的xhr,傳入id指定xhr(doupload時返回)或者預設取消最近一個。*/
abort(id) {
id === undefined ?
xhrList[currentXHRID].abort() :
xhrList[id].abort()
}
/*判斷ie版本*/
checkIE() {
const userAgent = this.userAgent;
const version = userAgent.indexOf('MSIE')
if (version < 0) return -1
return parseFloat(userAgent.substring(version + 5, userAgent.indexOf(';', version)))
}
/*生成假的IE上傳進度*/
fakeProgress() {
let add = 6
const decrease = 0.3,
end = 98,
min = 0.2
return (lastTime) => {
let start = lastTime
if (start >= end) return start
start += add
add = add - decrease
add < min && (add = min)
return start
}
}
getUserAgent() {
const userAgentString = this.props.options && this.props.options.userAgent;
const navigatorIsAvailable = typeof navigator !== 'undefined';
if (!navigatorIsAvailable && !userAgentString) {
throw new Error('\`options.userAgent\` must be set rendering react-fileuploader in situations when \`navigator\` is not defined in the global namespace. (on the server, for example)');
}
return navigatorIsAvailable ? navigator.userAgent : userAgentString;
}
componentWillMount() {
this.userAgent = this.getUserAgent();
this.isIE = !(this.checkIE() < 0 || this.checkIE() >= 10)
/*因為IE每次要用到很多form組,如果在同一頁面需要用到多個<FileUpload>可以在options傳入tag作為區分。並且不隨後續props改變而改變*/
const tag = this.props.options && this.props.options.tag
this.IETag = tag ? tag+'_' : ''
this._updateProps(this.props)
}
componentDidMount() {
}
componentWillReceiveProps(newProps) {
this._updateProps(newProps)
}
render() {
return this._packRender()
}
/*打包render函式*/
_packRender() {
/*IE用iframe表單上傳,其他用ajax Formdata*/
let render = ''
if (this.isIE) {
render = this._multiIEForm()
} else {
const restAttrs = {
accept: this.accept,
multiple: this.multiple
}
render = (
<div className={this.props.className} style={this.props.style}>
{this.state.before}
<div onClick={(e)=>{this.commonChooseFile(e)}}
style={{overflow:'hidden',postion:'relative',display:this.wrapperDisplay}}
>
{this.state.chooseBtn}
</div>
{this.state.middle}
<div onClick={(e)=>{this.commonUpload(e)}}
style={{
overflow: 'hidden',
postion: 'relative',
display: this.chooseAndUpload ? 'none' : this.wrapperDisplay
}}
>
{this.state.uploadBtn}
</div>
{this.state.after}
<input type="file" name="ajax_upload_file_input" ref="ajax_upload_file_input"
style={{display:'none'}} onChange={(e)=>{this.commonChange(e)}}
{...restAttrs}
/>
</div>
)
}
return render
}
/*IE多檔案同時上傳,需要多個表單+多個form組合。根據currentIEID代表有多少個form。*/
/*所有不在空閒(正在上傳)的上傳組都以display:none的形式插入,第一個空閒的上傳組會display:block捕捉。*/
_multiIEForm() {
const formArr = []
let hasFree = false
/* IE情況下,由於上傳按鈕被隱藏的input覆蓋,不能進行disabled按鈕處理。
* 所以當disabledIEChoose為true(或者func返回值為true)時,禁止IE上傳。
*/
const isDisabled =
typeof this.disabledIEChoose === 'function' ? this.disabledIEChoose() : this.disabledIEChoose
/*這裡IEFormGroup的長度會變,所以不能存len*/
for(let i = 0; i<IEFormGroup.length; i++) {
_insertIEForm.call(this,formArr,i)
/*如果當前上傳組是空閒,hasFree=true,並且指定當前上傳組ID*/
if(IEFormGroup[i] && !hasFree) {
hasFree = true
currentIEID = i
}
/*如果所有上傳組都不是空閒狀態,push一個新增組*/
(i==IEFormGroup.length-1) && !hasFree && IEFormGroup.push(true)
}
return (
<div className={this.props.className} style={this.props.style} id="react-file-uploader">
{formArr}
</div>
)
function _insertIEForm(formArr,i) {
/*如果已經push了空閒組而當前也是空閒組*/
if(IEFormGroup[i] && hasFree) return
/*是否display*/
const isShow = IEFormGroup[i]
/*Input內聯樣式*/
const style = {
position:'absolute',
left:'-30px',
top:0,
zIndex:'50',
fontSize:'80px',
width:'200px',
opacity:0,
filter:'alpha(opacity=0)'
}
/*是否限制了檔案字尾,以及是否disabled*/
const restAttrs = {
accept: this.accept,
disabled: isDisabled
}
const input =
<input type="file" name={`ajax_upload_hidden_input_${i}`} id={`ajax_upload_hidden_input_${i}`}
ref={`ajax_upload_hidden_input_${i}`} onChange={(e)=>{this.IEChooseFile(e)}} onClick={(e)=>{this.IEBeforeChoose(e)}}
style={style} {...restAttrs}
/>
i = `${this.IETag}${i}`
formArr.push((
<form id={`ajax_upload_file_form_${i}`} method="post" target={`ajax_upload_file_frame_${i}`}
key={`ajax_upload_file_form_${i}`}
encType="multipart/form-data" ref={`form_${i}`} onSubmit={(e)=>{this.IEUpload(e)}}
style={{display:isShow? 'block':'none'}}
>
{this.state.before}
<div style={{overflow:'hidden',position:'relative',display:'inline-block'}}>
{this.state.chooseBtn}
{/*input file 的name不能省略*/}
{input}
</div>
{this.state.middle}
<div style={{
overflow:'hidden',
position:'relative',
display:this.chooseAndUpload?'none':this.wrapperDisplay
}}
>
{this.state.uploadBtn}
<input type="submit"
style={{
position:'absolute',
left:0,
top:0,
fontSize:'50px',
width:'200px',
opacity:0
}}
/>
</div>
{this.state.after}
</form>
))
formArr.push((
<iframe id={`ajax_upload_file_frame_${i}`}
name={`ajax_upload_file_frame_${i}`}
key={`ajax_upload_file_frame_${i}`}
className="ajax_upload_file_frame"
style={{
display: 'none',
width: 0,
height: 0,
margin: 0,
border: 0
}}
>
</iframe>
))
}
}
}
FileUpload.propTypes = {
options: PT.shape({
/*basics*/
baseUrl: PT.string.isRequired,
param: PT.oneOfType([PT.object, PT.func]),
dataType: PT.string,
chooseAndUpload: PT.bool,
paramAddToField: PT.oneOfType([PT.object, PT.func]),
wrapperDisplay: PT.string,
timeout: PT.number,
accept: PT.string,
multiple: PT.bool,
numberLimit: PT.oneOfType([PT.number, PT.func]),
fileFieldName: PT.oneOfType([PT.string, PT.func]),
withCredentials: PT.bool,
requestHeaders: PT.object,
/*specials*/
tag: PT.string,
userAgent: PT.string,
disabledIEChoose: PT.oneOfType([PT.bool, PT.func]),
_withoutFileUpload: PT.bool,
filesToUpload: PT.arrayOf(PT.object),
textBeforeFiles: PT.bool,
/*funcs*/
beforeChoose: PT.func,
chooseFile: PT.func,
beforeUpload: PT.func,
doUpload: PT.func,
uploading: PT.func,
uploadSuccess: PT.func,
uploadError: PT.func,
uploadFail: PT.func,
onabort: PT.func
}).isRequired,
style: PT.object,
className: PT.string
};
export default FileUpload;
修改方法
- 將原始檔中
const FileUpload = React.createClass
方式建立的類改為class FileUpload extends React.Component
(記得刪掉多餘的小括號) - 使用yarn或npm命令安裝prop-types,在類外面指定FileUpload的propTypes屬性,
FileUpload.propTypes = {xxx}
,並將原始檔中propTypes
的屬性內容剪下到FileUpload.propTypes
中,然後刪除原始檔裡面的propTypes
- 最後由於從方法轉化到了類,需要將原始檔中多餘的逗號刪除
- 將修改好的檔案引入,即可在react@16.x的版本里使用react-fileupload
這樣就完成了原始檔的修改,實現react@16.x版本的相容問題
相關文章
- element上傳圖片元件使用方法|圖片回顯|格式轉換base64元件
- Vue圖片裁剪上傳元件Vue元件
- 圖片裁剪上傳示例(node + react)React
- 分享一個看起來很酷的圖片上傳元件元件
- 上傳圖片
- 一個Vue圖片上傳剪裁壓縮元件Vue元件
- El-Upload元件上傳圖片並新增水印元件
- 配置Django-TinyMCE元件支援上傳圖片功能Django元件
- React Native 圖片檢視元件React Native元件
- React Native圖片快取元件React Native快取元件
- PbootCMS上傳圖片變模糊、上傳圖片尺寸受限的解決方案boot
- AntD框架的upload元件上傳圖片時使用customRequest方法自定義上傳行為框架元件
- electron上傳圖片
- 上傳圖片jsJS
- 裁剪上傳圖片
- 圖片上傳及圖片處理
- 封裝react antd的upload上傳元件封裝React元件
- java,springboot + thymeleaf 上傳圖片、刪除圖片到伺服器、本地,壓縮圖片上傳(有些圖片會失真),原圖上傳JavaSpring Boot伺服器
- React Native 上傳圖片至七牛雲端儲存React Native
- 一個提取圖片顏色的React元件React元件
- Vue +Element Ui 使用Upload元件實現多圖片上傳VueUI元件
- 微信小程式簡單封裝圖片上傳元件微信小程式封裝元件
- 多圖片formpost上傳ORM
- spring boot 圖片上傳Spring Boot
- 測試圖片上傳
- input file圖片上傳
- 本地Markdown上傳圖片
- ci框架中的圖片上傳框架
- 基於SpringMVC的上傳圖片SpringMVC
- 基於WebUploader的圖片上傳Web
- mino如何上傳同名的圖片
- 上傳圖片 以及做成縮圖
- vue 上傳圖片進行壓縮圖片Vue
- Ueditor 上傳圖片自動新增水印(只能上傳圖片,上傳檔案報錯)
- react ts 使用七牛 傳輸圖片React
- Java實現圖片上傳到伺服器,並把上傳的圖片讀取出來Java伺服器
- js上傳圖片壓縮JS
- 圖片上傳方案詳解