diff --git a/HISTORY.md b/HISTORY.md index 88e45e5a..2b3e18a9 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,10 @@ # History ---- +### 3.0.0 + +- Drop support of IE8/9. + ### 2.9.0 - Support `method`. #197 diff --git a/README.md b/README.md index 73cc5ec9..8a1cfd88 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ online example: http://react-component.github.io/upload/examples/simple.html ## Feature -* support ie8,ie8+,chrome,firefox,safari +* support IE11+, Chrome, Firefox, Safari ## install @@ -58,7 +58,6 @@ React.render(, container); |className | string | - | root component className | |disabled | boolean | false | whether disabled | |component | "div"|"span" | "span"| wrap component name | -|supportServerRender | boolean | false| whether to support server render | |onReady | function | | only call when supportServerRender is true, upload is rendered completely | |action| string | function(file): string | Promise<string> | | form action url | |method | string | post | request method | @@ -112,28 +111,6 @@ customRequest callback is passed an object with: abort(file?: File) => void: abort the uploading file - -### IE8/9 Note - -#### Download Popup Problem - -In iframe uploader way, the content-type of response should be `text/plain` or `text/html`. [See more about -Content-Type Negotiation](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation) - -What's more, in iframe mode, the response's status should always be `200 OK`, otherwise you might get an `Access is denied` error in IE 8/9. - -#### Domain Problem - -If the Page set document.domain, then server should output document.domain according to _documentDomain parameter. - -```js -var ret = ''; -if (postData._documentDomain) { - ret += ''; -} -this.body = ret + '{"url":"xx.jpq"}'; -``` - ## License rc-upload is released under the MIT license. diff --git a/package.json b/package.json index 4c1c0ca1..4e8f2679 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rc-upload", - "version": "2.9.4", + "version": "3.0.0-alpha.0", "description": "upload ui component for react", "keywords": [ "react", @@ -54,9 +54,7 @@ ], "dependencies": { "babel-runtime": "6.x", - "classnames": "^2.2.5", - "prop-types": "^15.5.7", - "warning": "4.x" + "classnames": "^2.2.5" }, "jest": { "collectCoverageFrom": [ diff --git a/src/AjaxUploader.jsx b/src/AjaxUploader.jsx index f98565f2..bf7a7172 100644 --- a/src/AjaxUploader.jsx +++ b/src/AjaxUploader.jsx @@ -1,7 +1,5 @@ -/* eslint react/no-is-mounted:0 react/sort-comp:0 */ - +/* eslint react/no-is-mounted:0,react/sort-comp:0,react/prop-types:0 */ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import classNames from 'classnames'; import defaultRequest from './request'; import getUid from './uid'; @@ -9,35 +7,6 @@ import attrAccept from './attr-accept'; import traverseFileTree from './traverseFileTree'; class AjaxUploader extends Component { - static propTypes = { - id: PropTypes.string, - component: PropTypes.string, - style: PropTypes.object, - prefixCls: PropTypes.string, - className: PropTypes.string, - multiple: PropTypes.bool, - directory: PropTypes.bool, - disabled: PropTypes.bool, - accept: PropTypes.string, - children: PropTypes.any, - onStart: PropTypes.func, - data: PropTypes.oneOfType([ - PropTypes.object, - PropTypes.func, - ]), - action: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.func, - ]), - headers: PropTypes.object, - beforeUpload: PropTypes.func, - customRequest: PropTypes.func, - onProgress: PropTypes.func, - withCredentials: PropTypes.bool, - openFileDialogOnClick: PropTypes.bool, - transformFile: PropTypes.func, - } - state = { uid: getUid() } reqs = {} diff --git a/src/IframeUploader.jsx b/src/IframeUploader.jsx deleted file mode 100644 index 102f344c..00000000 --- a/src/IframeUploader.jsx +++ /dev/null @@ -1,303 +0,0 @@ -/* eslint react/sort-comp:0 */ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import ReactDOM from 'react-dom'; -import classNames from 'classnames'; -import getUid from './uid'; -import warning from 'warning'; - -const IFRAME_STYLE = { - position: 'absolute', - top: 0, - opacity: 0, - filter: 'alpha(opacity=0)', - left: 0, - zIndex: 9999, -}; - -// diferent from AjaxUpload, can only upload on at one time, serial seriously -class IframeUploader extends Component { - static propTypes = { - component: PropTypes.string, - style: PropTypes.object, - disabled: PropTypes.bool, - prefixCls: PropTypes.string, - className: PropTypes.string, - accept: PropTypes.string, - onStart: PropTypes.func, - multiple: PropTypes.bool, - children: PropTypes.any, - data: PropTypes.oneOfType([ - PropTypes.object, - PropTypes.func, - ]), - action: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.func, - ]), - name: PropTypes.string, - } - - state = { uploading: false } - - file = {} - - onLoad = () => { - if (!this.state.uploading) { - return; - } - const { props, file } = this; - let response; - try { - const doc = this.getIframeDocument(); - const script = doc.getElementsByTagName('script')[0]; - if (script && script.parentNode === doc.body) { - doc.body.removeChild(script); - } - response = doc.body.innerHTML; - props.onSuccess(response, file); - } catch (err) { - warning(false, 'cross domain error for Upload. Maybe server should return document.domain script. see Note from https://github.com/react-component/upload'); - response = 'cross-domain'; - props.onError(err, null, file); - } - this.endUpload(); - } - - onChange = () => { - const target = this.getFormInputNode(); - // ie8/9 don't support FileList Object - // http://stackoverflow.com/questions/12830058/ie8-input-type-file-get-files - const file = (this.file = { - uid: getUid(), - name: - target.value && - target.value.substring(target.value.lastIndexOf('\\') + 1, target.value.length), - }); - this.startUpload(); - const { props } = this; - if (!props.beforeUpload) { - return this.post(file); - } - const before = props.beforeUpload(file); - if (before && before.then) { - before.then(() => { - this.post(file); - }, () => { - this.endUpload(); - }); - } else if (before !== false) { - this.post(file); - } else { - this.endUpload(); - } - } - - componentDidMount() { - this.updateIframeWH(); - this.initIframe(); - } - - componentDidUpdate() { - this.updateIframeWH(); - } - - getIframeNode() { - return this.iframe; - } - - getIframeDocument() { - return this.getIframeNode().contentDocument; - } - - getFormNode() { - return this.getIframeDocument().getElementById('form'); - } - - getFormInputNode() { - return this.getIframeDocument().getElementById('input'); - } - - getFormDataNode() { - return this.getIframeDocument().getElementById('data'); - } - - getFileForMultiple(file) { - return this.props.multiple ? [file] : file; - } - - getIframeHTML(domain) { - let domainScript = ''; - let domainInput = ''; - if (domain) { - const script = 'script'; - domainScript = `<${script}>document.domain="${domain}";`; - domainInput = ``; - } - return ` - - - - - - ${domainScript} - - -
- - ${domainInput} - -
- - - `; - } - - initIframeSrc() { - if (this.domain) { - this.getIframeNode().src = `javascript:void((function(){ - var d = document; - d.open(); - d.domain='${this.domain}'; - d.write(''); - d.close(); - })())`; - } - } - - initIframe() { - const iframeNode = this.getIframeNode(); - let win = iframeNode.contentWindow; - let doc; - this.domain = this.domain || ''; - this.initIframeSrc(); - try { - doc = win.document; - } catch (e) { - this.domain = document.domain; - this.initIframeSrc(); - win = iframeNode.contentWindow; - doc = win.document; - } - doc.open('text/html', 'replace'); - doc.write(this.getIframeHTML(this.domain)); - doc.close(); - this.getFormInputNode().onchange = this.onChange; - } - - endUpload() { - if (this.state.uploading) { - this.file = {}; - // hack avoid batch - this.state.uploading = false; - this.setState({ - uploading: false, - }); - this.initIframe(); - } - } - - startUpload() { - if (!this.state.uploading) { - this.state.uploading = true; - this.setState({ - uploading: true, - }); - } - } - - updateIframeWH() { - const rootNode = ReactDOM.findDOMNode(this); - const iframeNode = this.getIframeNode(); - iframeNode.style.height = `${rootNode.offsetHeight}px`; - iframeNode.style.width = `${rootNode.offsetWidth}px`; - } - - abort(file) { - if (file) { - let uid = file; - if (file && file.uid) { - uid = file.uid; - } - if (uid === this.file.uid) { - this.endUpload(); - } - } else { - this.endUpload(); - } - } - - post(file) { - const formNode = this.getFormNode(); - const dataSpan = this.getFormDataNode(); - let { data } = this.props; - const { onStart } = this.props; - if (typeof data === 'function') { - data = data(file); - } - const inputs = document.createDocumentFragment(); - for (const key in data) { - if (data.hasOwnProperty(key)) { - const input = document.createElement('input'); - input.setAttribute('name', key); - input.value = data[key]; - inputs.appendChild(input); - } - } - dataSpan.appendChild(inputs); - new Promise(resolve => { - const { action } = this.props; - if (typeof action === 'function') { - return resolve(action(file)); - } - resolve(action); - }).then(action => { - formNode.setAttribute('action', action); - formNode.submit(); - dataSpan.innerHTML = ''; - onStart(file); - }); - } - - saveIframe = (node) => { - this.iframe = node; - } - - render() { - const { - component: Tag, disabled, className, - prefixCls, children, style, - } = this.props; - const iframeStyle = { - ...IFRAME_STYLE, - display: this.state.uploading || disabled ? 'none' : '', - }; - const cls = classNames({ - [prefixCls]: true, - [`${prefixCls}-disabled`]: disabled, - [className]: className, - }); - return ( - -