解决jQuery uploadify在非IE核心浏览器下无法上传


Posted in Javascript onAugust 05, 2015

一、jquery uploadify自我介绍:

  (1)、大家好,我是jquery插件大家族中负责实现异步上传的插件,我不是唯一,只是较好用的一款。

  (2)、我的功能:

支持单文件或多文件上传,可控制并发上传的文件数

在服务器端支持各种语言与之配合使用,诸如PHP,.NET,Java……

通过参数可配置上传文件类型及大小限制

通过参数可配置是否选择文件后自动上传

易于扩展,可控制每一步骤的回调函数(onSelect, onCancel……)

通过接口参数和CSS控制外观

Uploadify主页地址:http://www.uploadify.com/ 在该页面你可以了解到关于他的更多内容。

   (3)、我的用法:

          去baidu.com,google.com  search search,很多。

二、firefox下我出故障了,是我的问题吗?

      jquery uploadify在ie下可以正常上传,在实现异步上传的时候,每一个文件在上传时都会提交给服务器一个请求。每个请求都需要安全验证,session和cookie的校验。是的,就是这样。由于jquery uploadify是借助flash来实现上传的,每一次向后台发送数据流请求时,ie会自动把本地cookie存储捆绑在一起发送给服务器。但firefox、chrome不会这样做,他们会认为这样不安全。哈,这就是原因。

      找到原因了,在让我们来明白两个概念:

      (1)、session:

        Session又称为会话状态,是Web系统中最常用的状态,用于维护和当前浏览器实例相关的一些信息。举个例子来说,我们可以把已登录用户的用户名放在Session中,这样就能通过判断Session中的某个Key来判断用户是否登录,如果登录的话用户名又是多少。

        我们知道,Session对于每一个客户端(或者说浏览器实例)是“人手一份”,用户首次与Web服务器建立连接的时候,服务器会给用户分发一个 SessionID作为标识。SessionID是一个由24个字符组成的随机字符串。用户每次提交页面,浏览器都会把这个SessionID包含在 HTTP头中提交给Web服务器,这样Web服务器就能区分当前请求页面的是哪一个客户端。那么,ASP.NET 2.0提供了哪些存储SessionID的模式呢!

      (2)、Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。

三、解决方案

1.asp.net环境下

在Global.asax文件中,编写如下代码:

void Application_BeginRequest(object sender, EventArgs e)  
  {
    try { 
      string session_param_name = "ASPSESSID"; 
      string session_cookie_name = "ASP.NET_SessionId"; 
      if (HttpContext.Current.Request.Form[session_param_name] != null) 
      { 
        UpdateCookie(session_cookie_name, HttpContext.Current.Request.Form[session_param_name]); 
      } 
      else if (HttpContext.Current.Request.QueryString[session_param_name] != null) 
      { 
        UpdateCookie(session_cookie_name, HttpContext.Current.Request.QueryString[session_param_name]); 
      } 
    }
    catch { 
    } 

    //此处是身份验证
    try { 
      string auth_param_name = "AUTHID"; 
      string auth_cookie_name = FormsAuthentication.FormsCookieName; 
      if (HttpContext.Current.Request.Form[auth_param_name] != null) 
      { 
        UpdateCookie(auth_cookie_name, HttpContext.Current.Request.Form[auth_param_name]); 
      } 
      else if (HttpContext.Current.Request.QueryString[auth_param_name] != null) 
      { 
        UpdateCookie(auth_cookie_name, HttpContext.Current.Request.QueryString[auth_param_name]);
      } 
    }
    catch { }
  }

  private void UpdateCookie(string cookie_name, string cookie_value)
  {
    HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookie_name);
    if (null == cookie)
    {
      cookie = new HttpCookie(cookie_name);
    }
    cookie.Value = cookie_value;
    HttpContext.Current.Request.Cookies.Set(cookie);//重新设定请求中的cookie值,将服务器端的session值赋值给它
  }

   /*---------------------------Aspx页面端代码---------------------------------*/

this.hfAuth.Value = Request.Cookies[FormsAuthentication.FormsCookieName] == null ? string.Empty : Request.Cookies[FormsAuthentication.FormsCookieName].Value;
   

   this.hfAspSessID.Value = Session.SessionID;

      把session值及身份验证值保存到客户端控件中,然后你就可以通过js获取这两个值,然后传给下面的插件js初始化程序。

     (之所以选择将session值放入到控件中存储,也是怕客户端禁用cookie的考虑。)

   /*-----------------------------以下是js代码----------------------------------*/

InitUpload: function(auth, AspSessID) {
    $("#uploadify").uploadify({
      uploader: 'Scripts/jqueryplugins/Infrastructure/uploadify.swf',
      script: 'Handlers/ResourceHandler.ashx?OpType=UploadResource',
      cancelImg: 'Scripts/jqueryplugins/Infrastructure/cancel.png',
      queueID: 'fileQueue',
      sizeLimit: '21480000000',
      wmode: 'transparent ',
      fileExt: '*.zip,*.jpg, *.rar,*.doc,*.docx,*.xls,*.xlsx,*.png,*.pptx,*.ppt,*.pdf,*.swf,*.txt',
      auto: false,
      multi: true,
      scriptData: { ASPSESSID: AspSessID, AUTHID: auth },

            ...........//更多配置项,您可以查看官方配置文档

       在插件初始化的时候,把本地记录下来的session值,以及身份验证值传给初始化方法,进行参数赋值,这样,每次异步请求上传文件的时候,相应的 session值就包含在请求文件中了。

2.C#环境下

以上是asp.net下的解决方法,那么C#中应该如何处理呢?

我是这样解决的,这样所有上传文件的代码都不需要修改,改动量最小,但是有安全隐患:

if (this.LoginInfo == null)
{
  // 解决uploadify兼容火狐谷歌浏览器上传问题
  // 但是,此代码使系统有安全隐患,Flash程序请求该系统不需要验证
  // 要解决此安全隐患,需要Flash程序传用户名和密码过来验证,但是该用户名和密码不能写在前端以便被不法用户看到
  if (Request.UserAgent == "Shockwave Flash")
  {
    return;
  }
  else
  {
    filterContext.Result = RedirectToAction("LoginAgain", "Account", new { Area = "Auth" });
    return;
  }
}

我们的系统是ASP.NET MVC的,虽说通过加密的方式可以让用户看不到敏感信息,但恶意用户不需要把敏感信息解密出来就可绕过系统验证。

验证信息不能直接写前台,可以用ajax从后台获取验证信息,然后传给flash,然后在拦截器中验证。

修改后:

JS代码:

ajax请求后台获取用户名,传给flash

$(function () {
  $.ajax({
    url: "/Auth/Account/GetUserNamePwd",
    type: "POST",
    dataType: "json",
    data: {},
    success: function (data) {
      $("#uploadify").uploadify({
        height: 25,
        width: 100,
        swf: '/Content/Plugins/UploadifyJs/uploadify.swf',
        uploader: 'UploadFile',
        formData: {
          userName: data.data.userName, //ajax获取的用户名
          pwd: data.data.pwd //ajax获取的密码
        },
        buttonText: '选择文件上传',
        fileSizeLimit: '4MB',
        fileTypeDesc: '文件',
        fileTypeExts: '*.*',
        queueID: 'fileQueue',
        multi: true,
        onUploadSuccess: function (fileObj, data, response) {
          var d = eval("(" + data + ")");
          $(".uploadify-queue-item").find(".data").html("  上传完成");
          $("#url").val(d.url);
          $("#name").val(d.name);
        },
        onUploadError: function (event, ID, fileObj, errorObj) {
          if (event.size > 4 * 1024 * 1024) {
            alert('超过文件上传大小限制(4M)!');
            return;
          }
          alert('上传失败');
        }
      }); //end uploadify
    }
  });
});    //end $

拦截器中代码:

......
if (this.LoginInfo == null)
{ 
  // 解决uploadify兼容火狐谷歌浏览器上传问题
  // 但是,此代码使系统有安全隐患,Flash程序请求该系统不需要验证
  // 要解决此安全隐患,需要Flash程序传用户名和密码过来验证,但是该用户名和密码不能写在前端以便被不法用户看到
  if (Request.UserAgent == "Shockwave Flash")
  {
    string userName = Request.Params["userName"];
    string pwd = Request.Params["pwd"];
    if (!string.IsNullOrWhiteSpace(userName) && !string.IsNullOrWhiteSpace(pwd))
    {
      AuthDAL authDAL = new AuthDAL();
      sys_user user = authDAL.GetUserInfoByName(userName);
      if (user != null && user.password == pwd)
      {
        return;
      }
    }
  }
  else
  {
    filterContext.Result = RedirectToAction("LoginAgain", "Account", new { Area = "Auth" });
    return;
  }
}
......

3.jsp版解决方法

<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">


<%
	String syscontext = request.getContextPath();

%>

<% 
  String path = request.getContextPath(); 
  String basePath = request.getScheme() + "://" 
      + request.getServerName() + ":" + request.getServerPort() 
      + path; 
  
  String sessionid = session.getId();
  
%>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="<%=syscontext %>/webcontent/resourceManage/wallpapaer/uploadify/uploadify.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="<%=syscontext %>/webcontent/resourceManage/wallpapaer/uploadify/jquery.uploadify-3.1.min.js"></script>

<!-- 注意我使用的jquery uploadify版本-->


<script type="text/javascript">
//用来计算上传成功的图片数
var successCount = 1;

$(function() {
	var uploadUrl = '<%=basePath%>/uploadresource.do;jsessionid=<%=sessionid%>?Func=uploadwallpaper2Dfs';
	
	var swfUrl2 = "<%=basePath%>/webcontent/resourceManage/wallpapaer/uploadify/uploadify.swf";
  $('#file_upload').uploadify({
    'swf'   : swfUrl2,
    'uploader' : uploadUrl,
    // Put your options here
    'removeCompleted' : false,
    'auto' : false,
    'method'  : 'post',
    'onUploadSuccess' : function(file, data, response) {
      add2SuccessTable(data);
    }
  });
});



/**
 * 将成功上传的图片展示出来
 */
function add2SuccessTable(data){
	var jsonObj = JSON.parse(data);
	for(var i =0; i < jsonObj.length; i++){
		var oneObj = jsonObj[i];
		var fileName = oneObj.fileName;
		var imgUrl = oneObj.imgUrl;
		
		var td_FileName = "<td>"+fileName+"</td>";
		var td_imgUrl = "<td><img width='150' src='"+imgUrl+"'></img></td>";
		var oper = "<td><input type='button' value='删除' onclick='deleteRow("+successCount+")'/></td>";
		var tr = "<tr id='row"+successCount+"'>"+successCount+td_FileName+td_imgUrl+oper+"</tr>";
		
		$("#successTable").append(tr);
		
		successCount++;
	}
	
}



function deleteRow(i){
	$("#row"+i).empty();
	$("#row"+i).remove();
}
</script>


<title>Insert title here</title>
</head>
<body>
<input type="file" name="file_upload" id="file_upload" />
	<p> 
		<a href="javascript:$('#file_upload').uploadify('upload','*')">开始上传</a>  
		<a href="javascript:$('#file_upload').uploadify('cancel', '*')">取消所有上传</a>
	</p> 
<table id="successTable">
	<tr>
		<td>文件名</td>
		<td>图片</td>
		<td>操作</td>
	</tr>
</table>
</body>
</html>

总结

简单的说,最终的解决办法就是可以在每个引用的文件后面加个随机数,让它每次请求都带个参数,该问题则自动解决

Javascript 相关文章推荐
JAVASCRIPT HashTable
Jan 22 Javascript
Code:loadScript( )加载js的功能函数
Feb 02 Javascript
JavaScript网页制作特殊效果用随机数
May 22 Javascript
js禁止document element对象选中文本实现代码
Mar 21 Javascript
javascript计算用户打开网页的停留时间
Jan 09 Javascript
js基于setTimeout与setInterval实现多线程
Jun 17 Javascript
jQuery实现倒计时功能 jQuery实现计时器功能
Sep 19 jQuery
vue 循环加载数据并获取第一条记录的方法
Sep 26 Javascript
jQuery AJAX与jQuery事件的分析讲解
Feb 18 jQuery
微信小程序一周时间表功能实现
Oct 17 Javascript
React实现阿里云OSS上传文件的示例
Aug 10 Javascript
Vue如何跨组件传递Slot的实现
Dec 14 Vue.js
JS基于cookie实现来宾统计记录访客信息的方法
Aug 04 #Javascript
JavaScript采用递归算法计算阶乘实例
Aug 04 #Javascript
基于js实现投票的实例代码
Aug 04 #Javascript
JavaScript数组对象赋值用法实例
Aug 04 #Javascript
JavaScript取得键盘按下方向键是哪个的方法
Aug 04 #Javascript
JavaScript使用encodeURI()和decodeURI()获取字符串值的方法
Aug 04 #Javascript
javascript将DOM节点添加到文档的方法实例分析
Aug 04 #Javascript
You might like
PHP文本数据库的搜索方法
2006/10/09 PHP
php中time()和mktime()方法的区别
2013/09/28 PHP
如何解决PHP无法实现多线程的问题
2015/09/25 PHP
PHP数组生成XML格式数据的封装类实例
2016/11/10 PHP
php实现有序数组旋转后寻找最小值方法
2018/09/27 PHP
javascript中的new使用
2010/03/20 Javascript
yepnope.js使用详解及示例分享
2014/06/23 Javascript
基于编写jQuery的无缝滚动插件
2014/08/02 Javascript
jQuery中fadeOut()方法用法实例
2014/12/24 Javascript
js实现的简洁网页滑动tab菜单效果代码
2015/08/24 Javascript
Nodejs下用submit提交表单提示cannot post错误的解决方法
2016/11/21 NodeJs
微信小程序之仿微信漂流瓶实例
2016/12/09 Javascript
原生JS实现导航下拉菜单效果
2020/11/25 Javascript
VSCode配置react开发环境的步骤
2017/12/27 Javascript
tween.js缓动补间动画算法示例
2018/02/13 Javascript
新版小程序登录授权的方法
2018/12/12 Javascript
详解Vue.js和layui日期控件冲突问题解决办法
2019/07/25 Javascript
TypeScript之调用栈的实现
2019/12/31 Javascript
vue+canvas实现拼图小游戏
2020/09/18 Javascript
python如何通过protobuf实现rpc
2016/03/06 Python
Python常见异常分类与处理方法
2017/06/04 Python
使用Python监控文件内容变化代码实例
2018/06/04 Python
详解Python读取yaml文件多层菜单
2019/03/23 Python
基于python实现从尾到头打印链表
2019/11/02 Python
Python+OpenCV 实现图片无损旋转90°且无黑边
2019/12/12 Python
python基于socket模拟实现ssh远程执行命令
2020/12/05 Python
细说CSS3中box属性中的overflow-x属性和overflow-y属性值的效果
2014/07/21 HTML / CSS
卡西欧G-SHOCK英国官网: 防水防震手表
2018/01/08 全球购物
黄河象教学反思
2014/02/10 职场文书
机修工工作职责
2014/02/21 职场文书
人力资源部经理助理岗位职责
2014/03/04 职场文书
教师考察材料范文
2014/06/03 职场文书
公司活动总结怎么写
2014/06/25 职场文书
给老婆道歉的话
2015/01/20 职场文书
一个都不能少观后感
2015/06/04 职场文书
2019幼儿教师求职信(3篇)
2019/09/20 职场文书