1. jquery Uploadify 自己紹介:
(1) 皆さん、こんにちは。私は jquery プラグイン ファミリで非同期アップロードの実装を担当しているプラグインです。私だけが使いやすいわけではありません。
(2)、私の機能:
単一ファイルまたは複数ファイルのアップロードをサポートし、同時にアップロードされるファイルの数を制御できます
PHP、.NET、Java など、サーバー側で使用するさまざまな言語をサポートします。
アップロードされるファイルの種類とサイズ制限はパラメータで設定できます
ファイルを選択した後に自動的にアップロードするかどうかはパラメータで設定できます
拡張が簡単で、各ステップのコールバック関数 (onSelect、onCancel...) を制御できます
インターフェースパラメータと CSS を通じて外観を制御
ホームページのアドレスをアップロードしてください: http://www.uploadify.com/ このページで彼について詳しく知ることができます。
(3)、私の使用法:
baidu.com、google.com 検索にアクセスしてください。たくさんあります。
2. Firefox に問題があります。それは私の問題ですか?
jquery Uploadify は IE で正常にアップロードできます。非同期アップロードを実装すると、アップロード時に各ファイルがサーバーにリクエストを送信します。各リクエストには、セキュリティ検証、セッションおよび Cookie の検証が必要です。はい、それだけです。 jquery Uploadify はフラッシュを使用してアップロードを実装するため、データ フロー リクエストがバックグラウンドに送信されるたびに、IE はローカル Cookie ストレージを自動的にバンドルしてサーバーに送信します。しかし、Firefox と Chrome はこれを行わず、安全ではないと考えるでしょう。はー、だから。
理由がわかったので、次の 2 つの概念を理解しましょう:
(1)、セッション:
セッション (セッション状態とも呼ばれる) は、Web システムで最も一般的に使用される状態であり、現在のブラウザー インスタンスに関連する情報を維持するために使用されます。たとえば、ログインしているユーザーのユーザー名をセッションに入れることで、セッション内の特定のキーを判断することでユーザーがログインしているかどうか、ログインしている場合はそのユーザー名を判断できます。
セッションはクライアント (またはブラウザ インスタンス) ごとに「1 つのコピー」であることがわかっています。ユーザーが初めて Web サーバーとの接続を確立すると、サーバーは識別子として SessionID をユーザーに配布します。 SessionID は 24 文字のランダムな文字列です。ユーザーがページを送信するたびに、ブラウザーは HTTP ヘッダーに SessionID を含めて Web サーバーに送信します。これにより、Web サーバーは現在ページを要求しているクライアントを区別できます。では、ASP.NET 2.0 では、SessionID を保存するどのようなモードが提供されているのでしょうか?
(2) Cookie (Cookie という複数形で使用されることもあります) は、ユーザーの身元を特定し、セッション追跡を実行するために、特定の Web サイトによってユーザーのローカル端末に保存されるデータ (通常は暗号化された) を指します。
3. 解決策
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;
セッション値と認証値をクライアント コントロールに保存すると、js を通じてこれら 2 つの値を取得し、次のプラグイン js 初期化プログラムに渡すことができます。
(セッション値をコントロールに保存することを選択した理由は、クライアントが 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 },
しかし
プラグインが初期化されるとき、ローカルに記録されたセッション値と認証値をパラメータ割り当ての初期化メソッドに渡します。このようにして、ファイルをアップロードするための非同期リクエストが行われるたびに、対応するセッション値が返されます。リクエストファイルに含まれています。
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; } }
検証情報をフロントエンドに直接書き込むことはできません。ajax を使用してバックエンドから検証情報を取得し、それをフラッシュに渡し、インターセプターで検証することができます。
変更後:
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>
总结
简单的说,最终的解决办法就是可以在每个引用的文件后面加个随机数,让它每次请求都带个参数,该问题则自动解决