解决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 相关文章推荐
jQuery Ajax 全解析
Feb 08 Javascript
JS 弹出层 定位至屏幕居中示例
May 21 Javascript
JQuery实现的图文自动轮播效果插件
Jun 19 Javascript
客户端验证用户名和密码的方法详解
Jun 16 Javascript
JavaScript中Promise的使用详解
Feb 26 Javascript
详解前端路由实现与react-router使用姿势
Aug 07 Javascript
Vue中android4.4不兼容问题的解决方法
Sep 04 Javascript
jQuery实现点击图标div循环放大缩小功能
Sep 30 jQuery
iView框架问题整理小结
Oct 16 Javascript
JavaScript数据结构与算法之检索算法实例分析【顺序查找、最大最小值、自组织查询】
Feb 22 Javascript
js实现表格单列按字母排序
Aug 12 Javascript
vue项目配置同一局域网可使用ip访问的操作
Oct 23 Javascript
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读取大文件的类SplFileObject使用介绍
2014/04/09 PHP
MySql数据库查询结果用表格输出PHP代码示例
2015/03/20 PHP
php构造方法中析构方法在继承中的表现
2016/04/12 PHP
PHP预定义变量9大超全局数组用法详解
2016/04/23 PHP
PHP convert_cyr_string()函数讲解
2019/02/13 PHP
PHP常见的几种攻击方式实例小结
2019/04/29 PHP
广告显示判断
2006/08/31 Javascript
Jquery 切换不同图片示例代码
2013/12/05 Javascript
javascript 动态修改css样式方法汇总(四种方法)
2015/08/27 Javascript
用JavaScript获取页面文档内容的实现代码
2016/06/10 Javascript
vue2.0中goods选购栏滚动算法的实现代码
2017/05/17 Javascript
vue实现导航栏效果(选中状态刷新不消失)
2017/12/13 Javascript
记React connect的几种写法(小结)
2018/09/18 Javascript
Vue从TodoList中学父子组件通信
2019/02/05 Javascript
小程序实现图片预览裁剪插件
2019/11/22 Javascript
Vue 实现简易多行滚动&quot;弹幕&quot;效果
2020/01/02 Javascript
Vue+Vant 图片上传加显示的案例
2020/11/03 Javascript
[59:36]2018DOTA2亚洲邀请赛 4.3 突围赛 Secret vs VG 第二场
2018/04/04 DOTA
[05:46]2018完美盛典-《同梦共竞》
2018/12/17 DOTA
Python实现远程调用MetaSploit的方法
2014/08/22 Python
在Django框架中编写Context处理器的方法
2015/07/20 Python
在DigitalOcean的服务器上部署flaskblog应用
2015/12/19 Python
python虚拟环境的安装配置图文教程
2017/10/20 Python
amazeui页面分析之登录页面的示例代码
2020/08/25 HTML / CSS
6PM官网:折扣鞋、服装及配饰
2018/08/03 全球购物
Lookfantastic美国/加拿大:英国知名美妆购物网站
2019/03/27 全球购物
shell程序中如何注释
2012/02/17 面试题
工程现场管理求职自荐信
2013/10/02 职场文书
大学毕业感言
2014/01/10 职场文书
医学专业应届生的自我评价
2014/02/28 职场文书
菜篮子工程实施方案
2014/03/08 职场文书
《李广射虎》教学反思
2014/04/27 职场文书
2014教师个人自我评价范文
2014/09/13 职场文书
男方婚前保证书
2015/02/28 职场文书
个人催款函范文
2015/06/24 职场文书
公司客户答谢酒会祝酒词
2015/08/11 职场文书