首页 > 语言 > JavaScript > 正文

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

2024-05-06 16:24:21
字体:
来源:转载
供稿:网友

之前上传了一个通过Flash实现多文件上传,但是在IE正常运行,FireFox 不能正常上传。经过反复研究学习,之所以firefox和360浏览器无法正常运行,是因为FireFox、chrome、360浏览器等支持HTML5的浏览器不会再文件上传时自动带入session信息和cookie,不共享session。

一、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文件中,编写如下代码:

 

 
  1. void Application_BeginRequest(object sender, EventArgs e)  
  2. try {  
  3. string session_param_name = "ASPSESSID";  
  4. string session_cookie_name = "ASP.NET_SessionId";  
  5. if (HttpContext.Current.Request.Form[session_param_name] != null)  
  6. {  
  7. UpdateCookie(session_cookie_name, HttpContext.Current.Request.Form[session_param_name]);  
  8. }  
  9. else if (HttpContext.Current.Request.QueryString[session_param_name] != null)  
  10. {  
  11. UpdateCookie(session_cookie_name, HttpContext.Current.Request.QueryString[session_param_name]);  
  12. }  
  13. catch {  
  14. }  
  15.  
  16. //此处是身份验证 
  17. try {  
  18. string auth_param_name = "AUTHID";  
  19. string auth_cookie_name = FormsAuthentication.FormsCookieName;  
  20. if (HttpContext.Current.Request.Form[auth_param_name] != null)  
  21. {  
  22. UpdateCookie(auth_cookie_name, HttpContext.Current.Request.Form[auth_param_name]);  
  23. }  
  24. else if (HttpContext.Current.Request.QueryString[auth_param_name] != null)  
  25. {  
  26. UpdateCookie(auth_cookie_name, HttpContext.Current.Request.QueryString[auth_param_name]); 
  27. }  
  28. catch { } 
  29.  
  30. private void UpdateCookie(string cookie_name, string cookie_value) 
  31. HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookie_name); 
  32. if (null == cookie) 
  33. cookie = new HttpCookie(cookie_name); 
  34. cookie.Value = cookie_value; 
  35. HttpContext.Current.Request.Cookies.Set(cookie);//重新设定请求中的cookie值,将服务器端的session值赋值给它 

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

?

1

2

3

4

 

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代码----------------------------------*/

 

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

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

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

2.C#环境下

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

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

 

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

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

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

修改后:

JS代码:

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

 

 
  1. $(function () { 
  2. $.ajax({ 
  3. url: "/Auth/Account/GetUserNamePwd"
  4. type: "POST"
  5. dataType: "json"
  6. data: {}, 
  7. success: function (data) { 
  8. $("#uploadify").uploadify({ 
  9. height: 25, 
  10. width: 100, 
  11. swf: '/Content/Plugins/UploadifyJs/uploadify.swf'
  12. uploader: 'UploadFile'
  13. formData: { 
  14. userName: data.data.userName, //ajax获取的用户名 
  15. pwd: data.data.pwd //ajax获取的密码 
  16. }, 
  17. buttonText: '选择文件上传'
  18. fileSizeLimit: '4MB'
  19. fileTypeDesc: '文件'
  20. fileTypeExts: '*.*'
  21. queueID: 'fileQueue'
  22. multi: true
  23. onUploadSuccess: function (fileObj, data, response) { 
  24. var d = eval("(" + data + ")"); 
  25. $(".uploadify-queue-item").find(".data").html("上传完成"); 
  26. $("#url").val(d.url); 
  27. $("#name").val(d.name); 
  28. }, 
  29. onUploadError: function (event, ID, fileObj, errorObj) { 
  30. if (event.size > 4 * 1024 * 1024) { 
  31. alert('超过文件上传大小限制(4M)!'); 
  32. return
  33. alert('上传失败'); 
  34. }); //end uploadify 
  35. }); 
  36. }); //end $ 

拦截器中代码:

 

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

3.jsp版解决方法

 

 
  1. <%@ page language="java" contentType="text/html; charset=UTF-8" 
  2. pageEncoding="UTF-8"%> 
  3.  
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"
  5.  
  6.  
  7. <% 
  8. String syscontext = request.getContextPath(); 
  9.  
  10. %> 
  11.  
  12. <%  
  13. String path = request.getContextPath();  
  14. String basePath = request.getScheme() + "://" 
  15. + request.getServerName() + ":" + request.getServerPort()  
  16. + path;  
  17.  
  18. String sessionid = session.getId(); 
  19.  
  20. %> 
  21.  
  22. <html> 
  23. <head> 
  24. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"
  25. <link rel="stylesheet" type="text/css" href="<%=syscontext %>/webcontent/resourceManage/wallpapaer/uploadify/uploadify.css" /> 
  26. <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script> 
  27. <script type="text/javascript" src="<%=syscontext %>/webcontent/resourceManage/wallpapaer/uploadify/jquery.uploadify-3.1.min.js"></script> 
  28.  
  29. <!-- 注意我使用的jquery uploadify版本--> 
  30.  
  31.  
  32. <script type="text/javascript"
  33. //用来计算上传成功的图片数 
  34. var successCount = 1; 
  35.  
  36. $(function() { 
  37. var uploadUrl = '<%=basePath%>/uploadresource.do;jsessionid=<%=sessionid%>?Func=uploadwallpaper2Dfs'
  38.  
  39. var swfUrl2 = "<%=basePath%>/webcontent/resourceManage/wallpapaer/uploadify/uploadify.swf"
  40. $('#file_upload').uploadify({ 
  41. 'swf' : swfUrl2, 
  42. 'uploader' : uploadUrl, 
  43. // Put your options here 
  44. 'removeCompleted' : false
  45. 'auto' : false
  46. 'method' : 'post'
  47. 'onUploadSuccess' : function(file, data, response) { 
  48. add2SuccessTable(data); 
  49. }); 
  50. }); 
  51.  
  52.  
  53.  
  54. /** 
  55. * 将成功上传的图片展示出来 
  56. */ 
  57. function add2SuccessTable(data){ 
  58. var jsonObj = JSON.parse(data); 
  59. for(var i =0; i < jsonObj.length; i++){ 
  60. var oneObj = jsonObj[i]; 
  61. var fileName = oneObj.fileName; 
  62. var imgUrl = oneObj.imgUrl; 
  63.  
  64. var td_FileName = "<td>"+fileName+"</td>"
  65. var td_imgUrl = "<td><img width='150' src='"+imgUrl+"'></img></td>"
  66. var oper = "<td><input type='button' value='删除' onclick='deleteRow("+successCount+")'/></td>"
  67. var tr = "<tr id='row"+successCount+"'>"+successCount+td_FileName+td_imgUrl+oper+"</tr>"
  68.  
  69. $("#successTable").append(tr); 
  70.  
  71. successCount++; 
  72.  
  73.  
  74.  
  75.  
  76. function deleteRow(i){ 
  77. $("#row"+i).empty(); 
  78. $("#row"+i).remove(); 
  79. </script> 
  80.  
  81.  
  82. <title>Insert title here</title> 
  83. </head> 
  84. <body> 
  85. <input type="file" name="file_upload" id="file_upload" /> 
  86. <p>  
  87. <a href="javascript:$('#file_upload').uploadify('upload','*')">开始上传</a> 
  88. <a href="javascript:$('#file_upload').uploadify('cancel', '*')">取消所有上传</a> 
  89. </p>  
  90. <table id="successTable"
  91. <tr> 
  92. <td>文件名</td> 
  93. <td>图片</td> 
  94. <td>操作</td> 
  95. </tr> 
  96. </table> 
  97. </body> 
  98. </html> 

总结

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选