前言
由于各大浏览器纷纷宣布不再支撑Flash插件,尤其提下Chrome,Chrome将于12月彻底结束对Adobe Flash Player的支持,导致很多使用了Flash插件的应用系统都要做对应的升级等.本文章是对系统使用的uploadfy插件(内置flash)替换为uploadfive的解决方案。
其他处理方法
之前由于工作或者排期原因,我们很多系统都不会马上对flash插件问题进行升级,所以往往是想法设法去设置浏览器允许flash插件的使用,我把之前我设置的步骤写上。
chorme设置允许flash使用:
a. 下载最新版flash(下载后可以通过chrome://components 查看flash的版本是否最新)
b. 添加flash允许网址chrome://settings/content/siteDetails?site= ,比如 chrome://settings/content/siteDetails?site=http://127.0.0.1,并设置权限中的flash为允许
c. 设置浏览器允许使用flash,chrome://settings/content/flash
d. 重启浏览器
OK,设置后浏览器可以使用flash了。但过了几天。。。发现又不行了,为什么呢?因为浏览器自动更新了,又恢复了设置。然后,又去重新设置浏览器,并且还把chrome自动更新服务禁用(该方式自行百度)。
自己的解决了,其他同事、用户的咋办?总不能一个个每次去帮他们设置吧?(尤其有个同事,windows服务里找不到chrome,也就是有新版chrome,他电脑必定更新的)。
我现在chrome的版本是88.0.4324.104,连设置flash的地方都已经不展示了。。
尴尬局面之后,痛定思痛,对系统对手吧,一次性解决,算是提升下用户体验度吧。
前期准备
uploadfive官网下载地址:http://www.uploadify.com(最终应该会转到https://github.com/RonnieSan/uploadify)
把jquery.uploadifive.js、uploadifive.css、uploadifive-cancel.png下载下来就行。
程序代码
- 前台页面代码:
<link href="<%=request.getContextPath() %>/commons/uploadify/uploadifive.css" rel="stylesheet" type="text/css" />
<script src="<%=request.getContextPath() %>/scripts/jquery.min.js" type="text/javascript"></script>
<script src="<%=request.getContextPath() %>/commons/uploadify/jquery.uploadifive.js" type="text/javascript"></script>
<div id="fileQueue"></div>
<form action="<%=path%>/upload" method="post" enctype="multipart/form-data">
<input type="file" name="uploadifive" id="uploadifive" />
</form>
<script type="text/javascript">
var uploadFiles = [];
var uploadFileObjs= [];
$(document).ready(function() {
$('#uploadifive').uploadifive({
'auto' : true,//是否自动上传
'multi' : false,//是否允许选择多文件
'formData' : {'formData':'GJB'},//设置提交参数
'buttonClass':'uploadifive-button',//按钮样式,可以看uploadifive.css。(根据系统风格自行修改颜色等)
'removeCompleted':false,//完成上传后移除文件,默认false
'folder' : 'uploads',//您想将文件保存到的路径(自己加的,uploadifive参数中并没有这个)
'buttonText':'浏览文件',
'fileType' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel', //文件类型(MIME类型),这里设置文件格式xls,xlsx
'cancelImg' : '<%=path%>/commons/uploadify/uploadifive-cancel.png',
'uploadLimit':1,//限制上传文件数
'queueSizeLimit':1,//一次可以在队列中拥有的最大文件数
'queueID' : 'fileQueue',//文件队列ID(展示上传文件列表用的 ,见上面div)
'uploadScript' : '<%=path%>/upload',//请求方法
'method': 'post',//提交方式
'overrideEvents' : ['onUploadComplete','onFallback','onError'],//重写方法集合,这个设置关键到下面自己写的方法是否会重写uploadifive.js中默认的方法实现(取消自带的错误提示)
'onUploadComplete' : function (fileObj, data) {//上传成功后触发方法
if(data){
fileObj.queueItem.find('.progress-bar').css('width', '100%');
fileObj.queueItem.find('.fileinfo').html(' - Completed');
fileObj.queueItem.find('.progress').slideUp(250);
fileObj.queueItem.addClass('complete');
var fp = eval('('+data+')').data;
if(uploadFileObjs.length>0){
javascript:$('#uploadifive').uploadifive('cancel',uploadFileObjs[0].id);
}
uploadFiles = [];
uploadFiles.push(encodeURI(fp));
uploadFileObjs.splice(0,uploadFileObjs.length);
uploadFileObjs.push(fileObj);
if($("#oldfile")){
$("#oldfile").hide(300);
}
}
},
'onFallback' : function() {//如果浏览器没有兼容的HTML5文件API功能触发
alert('浏览器不支持HTML5,无法上传!');
},
'onError': function (errorType, file) {//失败时触发
if (file != 0) {
var settings = $('#uploadifive').data('uploadifive').settings;
switch (errorType) {
case 'UPLOAD_LIMIT_EXCEEDED':
alert("上传的文件数量已经超出系统限制的" + settings.uploadLimit + "个文件!");
break;
case 'FILE_SIZE_LIMIT_EXCEEDED':
alert("文件 [" + file.name + "] 大小超出系统限制的" + $('#file_upload').uploadifive('settings', 'fileSizeLimit') + "大小!");
break;
case 'QUEUE_LIMIT_EXCEEDED':
alert("上传任务数量只允许" + settings.queueSizeLimit + "个!");
break;
case 'Invalid file type.':
case 'FORBIDDEN_FILE_TYPE':
alert("文件 [" + file.name + "] 类型不正确!");
break;
case '404_FILE_NOT_FOUND':
alert("文件未上传成功或服务器存放文件的文件夹不存在");
break;
}
}
}
});
});
</script>
- 后台JAVA代码
用的springMVC
非重点的就不贴上来了
/**
* 文件上传
* @param request
* @param response
* @param errors
* @return
* @throws Exception
*/
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public void fileUpload(HttpServletRequest request,
HttpServletResponse response)
throws Exception {
String filePath=null;
String formData = null;
String fileSuffix = null;//文件后缀
Boolean checkFile = true;
try {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
formData = multipartRequest.getParameter("formData");
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
String realPath = request.getServletContext().getRealPath("/WEB-INF");
String directoryPath = realPath.substring(0, realPath.length()-8)+PropertiesUtil.getValue("fileupload.directory.path");//配置文件中的附件路径
File file = new File(directoryPath);
if (!file.exists()) {
file.mkdirs();
}
filePath = null;
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
MultipartFile mf = entity.getValue();
fileSuffix = mf.getOriginalFilename().substring(
mf.getOriginalFilename().lastIndexOf("."));
if(null != formData && "GJB".equals(formData) && !".xls".equals(fileSuffix) && !".xlsx".equals(fileSuffix)){
checkFile = false;
}
filePath = directoryPath
+ File.separator
+ DateUtil.getDateTime(new Date(), "yyyyMMddHHmmss")+RandomUtils.nextInt(100000)
+ fileSuffix;
File uploadFile = new File(filePath);
FileCopyUtils.copy(mf.getBytes(), uploadFile);
logger.info("upload file success,path="+filePath);
}
} catch (Exception e) {
logger.error("file upload fail,directory path="+PropertiesUtil.getValue("fileupload.directory.path"));
this.printJSON(response,
JSONObject.fromObject(AjaxResponseUtils.ajaxFail()));
return;
}finally {
if(!checkFile){
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = null;
out = response.getWriter();
out.print("Invalid file type.");
out.close();
}else{
this.printJSON(response,
JSONObject.fromObject(AjaxResponseUtils.ajaxSuccess("file upload success",filePath)));
}
}
}
/**
* ajax return jsonObject
*
* @param response
* @param jsonObject
*/
protected void printJSON(HttpServletResponse response, JSONObject jsonObject) {
PrintWriter out = null;
response.setContentType("application/x-json;charset=UTF-8");
// response.setCharacterEncoding("UTF-8");
try {
out = response.getWriter();
out.println(jsonObject);
} catch (Exception e) {
LogFactory.getLog(BaseController.class).error(e.getMessage());
} finally {
out.close();
}
}
public final static String AJAX_RESPONSE_STATUS = "status";
public final static String AJAX_RESPONSE_STATUS_SUCCESS = "success";
public final static String AJAX_RESPONSE_STATUS_FAIL = "fail";
public final static String AJAX_RESPONSE_MESSAGE = "message";
public final static String AJAX_RESPONSE_DATA = "data";
pub
lic static Map<String,Object> ajaxSuccess(String message,Object data){
Map<String,Object> resultMap = new HashMap<String,Object>();
resultMap.put(AJAX_RESPONSE_STATUS, AJAX_RESPONSE_STATUS_SUCCESS);
resultMap.put(AJAX_RESPONSE_MESSAGE, message);
resultMap.put(AJAX_RESPONSE_DATA, data);
return resultMap;
}
这里有一段代码是判断文件类型的,这也是我看了uploadfive源码和测试后才这么做的,因为我发现,即使设置fileType参数,但上传其他类型的附件也是能上传的,而且不报错。这相比uploadfy就不行,uploadfy通过fileTypeExts设置文件类型,fileTypeDesc设置不符合文件类型时的提示,就能在选择文件后马上提示出来。
所以,很尴尬,很痛苦。只能自己解决了。如果其他大神对这个有不同见解,或者我理解错了,欢迎大家指正。(我也想不用自己写代码去解决这个问题的)
3.修改uploadfive.js部分代码
找到$data.uploadFile实现,下面代码中
// On complete function
xhr.addEventListener('load', function(e) {debugger;
if (this.readyState == 4) {
file.uploading = false;
if (this.status == 200) {
if (file.xhr.responseText !== 'Invalid file type.') {
$data.uploadComplete(e, file, uploadAll);
} else {
$data.error(file.xhr.responseText, file, uploadAll);
$data.removeQueueItem(file);//add by yangwz
}
} else if (this.status == 404) {
$data.error('404_FILE_NOT_FOUND', file, uploadAll);
} else if (this.status == 403) {
$data.error('403_FORBIDDEN', file, uploadAll);
} else {
$data.error('Unknown Error', file, uploadAll);
}
}
});
解读下这里的代码,file.xhr.responseText !== ‘Invalid file type.’ 这个条件正是我后台JAVA判断文件类型后返回Invalid file type.的原因,而且注意JAVA中输出用out.print(“Invalid file type.”),不要用out.println,因为有换行符都会匹配不上。
当然,判断文件类型也可以在js里自己写,只是个人不想动太多的源代码,所以不这样加了。(不过我感觉下面空行的地方官方原来是不是有这样的打算的,后面去掉了,这也只是我个人猜测)
$data.removeQueueItem(file);//add by yangwz
这段自己加上的,因为上传文件初始化绑定change方法时,就已经创建了上传文件对象,会在queueID页面展示出来,当文件类型校验不过,也不会删除,所以我自己加上这个删除的代码。
uploadfive我还做了两处修改,是对cancel动手的。
因为我删除上传的文件后,再选择文件上传会校验文件数不过。如下
所以在cancel中添加 d a t a . f i l e I D − − ; 和 data.fileID--;和 data.fileID−−;和data.uploads.count–; 为什么这么加可以看绑定change函数和uploadComplete实现的地方。
// Cancel a file upload in progress or remove a file from the queue
cancel : function(file, fast) {
this.each(function() {
var $this = $(this),
$data = $this.data('uploadifive'),
settings = $data.settings;
//……省略部分源码
if ($.inArray('onCancel', settings.overrideEvents) < 0) {
$data.fileID--;//add by yangwz
$data.uploads.count--;//add by yangwz
$data.removeQueueItem(file, fast);
}
// Trigger the cancel event
if (typeof settings.onCancel === 'function') {
settings.onCancel.call($this, file);
}
});
},
还有一点,是我重写onUploadComplete的
这段代码是看了源码下面这处地方才自己加上的
结语
这是根据项目中实际使用的情况来写的一个方案,flash插件影响的情况有很多种,文章只是提及一种涉及flash插件的解决方案。
如何文章中有什么写的不对的地方,欢迎大家指正,共同学习!