React在IE9下的文件上传方案
存在问题
在IE9上进行文件上传主要存在以下问题:
- IE9不支持formdata,也不支持File,所以ajax类提交无效。
- IE9下<input type=’file’/>,不支持mutiple,所以无法多选。
- 传统表单提交方式会导致页面刷新。刷新的后果就是state丢失,无法进行后续操作。
- IE9不能识别application/json,所以当你通过action提交一个表单,而后台是返回json时,IE就会把它当成一个文件下载下来。
解决方案
既然使用不了ajax提交,那么只能使用传统表单提交方式。
表单数据提交
其实antd的form.create()的结果也是在页面上生成了一个<form>,我们可以直接获取它。
let htmlForm = _this.formArea.getElementsByTagName("form")[0];
获取到这个form对象后,把它改造成传统表单。
htmlForm.setAttribute("method", "post"); htmlForm.setAttribute("enctype", "multipart/form-data"); htmlForm.setAttribute("action", serviceUrl + 'ws/uploadHtml?token=' + loginUser().token);
上面代码指定了表单传递的方法、编码、及后台响应地址。接下来处理我们要传递的值。首先定义了个公用方法,用于添加表单值。
function addInputElement(htmlForm, name, value) { let input = document.createElement("input"); input.setAttribute("name", name); input.setAttribute("type", "hidden"); input.setAttribute("value", value); htmlForm.appendChild(input); }
添加表单值
addInputElement(htmlForm, 'editableName', values.editableName); addInputElement(htmlForm, 'ajbs', _this.props.ajbs); addInputElement(htmlForm, 'fileType1', values.fileType1);
最后我们只要提交表单即可。
htmlForm.submit();
表单文件上传组件
利用html的file标签实现。该组件我已经写成公用组件,"rjd": "0.2.25",可使用此组件在ie9下通过传统模式上传文件,并且通过动态增加表单元素的方式解决了ie9不支持multiple的问题。
把它写在第一步中你的form组件里,即可在表单提交时提交文件。
无刷新页面
通过将表单的target指向页面内的iframe,则可以解决页面刷新问题。
如可在自定义表单组件后加一个<iframe>
在第一步骤设置表单属性时增加设置表单target
htmlForm.setAttribute("target", htmlIframe.name);
这样表单提交时就不会刷新整个页面了。
后端接口改造
IE9不能识别application/json,那么只能改造后端了,后端返回”text/plain”,前端通过JSON.parse进行解析。
后端代码示例
前端代码解析示例
关键参考代码
前端(instrument-component\components\wsUpload\uploadForm):
后端(court-splc-web\src\main\java\com\rjsoft\court\splc\web\controller\ws\YswsController.java):