前几天工作中用到了SWFUpload上传图片,涉及到跨域,因为前端无法实现跨域,所以只能把文件传到后端进行跨域请求,整理分享下。
效果图
前端 html部分
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>图片上传</title> <style> .divContent { float: left; margin-right: 20px; } .divDiv { border: 1px solid rgb(235, 235, 235); width: 150px; height: 150px; } .img { width: 150px; height: 150px; } .delImg { position: relative; top: -150px; right: -134px; cursor: pointer; } </style> </head> <body> <div> <div> <span id="spanButtonPlaceholder"></span><span id="imgNum">当前0张图片</span> </div> </div> <div class="TrDiv" id="imgUrl" style="margin-left:15px;"> </div> <script src="~/JS/SWFUpload/swfupload.js"></script> <script src="~/JS/SWFUpload/handlers.js"></script> <script src="~/JS/Common/jquery-1.7.1.min.js"></script> <script src="~/JS/UpLoad/upload.js"></script> <script type="text/javascript"> $(function () { upLoad.init(); }); </script> </body> </html>
前端JS SWFUpload处理
var upLoad = function () { var currentNum = 0; var totalNum = 0; var _initEvent = function () { initSwfu(); } var initSwfu = function () { var swfu; var file_queue_limit = 20;//队列1,每次只能上传1个,若是1个以上,上传后的样式是叠加图片 swfu = new SWFUpload({ upload_url: "/UpLoad/LocalReceive", post_params: { "Service": "MyServiceName", "Token": "b2ed46cd1bee4e5d816abdb1ec31b0f8" }, file_size_limit: "2 MB", //最大2M file_types: "*.jpg;*.png;*.gif;*.bmp", //设置选择文件的类型 file_types_description: "JPG Images", //描述文件类型 file_upload_limit: "0", //0代表不受上传个数的限制 file_queue_limit: file_queue_limit, file_queue_error_handler: fileQueueError, file_dialog_complete_handler: fileDialogComplete, //当关闭选择框后,做触发的事件 upload_progress_handler: uploadProgress, //处理上传进度 upload_error_handler: uploadError, //错误处理事件 upload_success_handler: uploadSuccess, //上传成功够,所处理的时间 upload_complete_handler: uploadComplete, //上传结束后,处理的事件 button_image_url: "/JS/SWFUpload/images/XPButtonNoText_160x22.png", button_placeholder_id: "spanButtonPlaceholder", button_width: 160, button_height: 22, //button_text: '', //button_text_style: '.spanButtonPlaceholder { font-family: Helvetica, Arial, sans-serif; font-size: 14pt;} ', button_text: '<span class="button">选择图片<span class="buttonSmall">(2 MB Max)</span></span>', button_text_style: '.button { font-family: Helvetica, Arial, sans-serif; font-size: 14pt; } .buttonSmall { font-size: 10pt; }', button_text_top_padding: 1, button_text_left_padding: 5, button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT, button_cursor: SWFUpload.CURSOR.HAND, flash_url: "/JS/SWFUpload/swfupload.swf", // Relative to this file custom_settings: { upload_target: "divFileProgressContainer" }, debug: false //是否开启日志 }); } //swfupload插件上传成功回调事件 function uploadSuccess(file, serverData) { var jsonData = eval('(' + serverData + ')');//{"Time":"\/Date(1481263944125)\/","Code":"100","Message":"成功","Url":"/Passport/2016/12/09/0c19c1ad07674e628deaad4acc289268.jpg"} if (jsonData.Code != "100") { alert(jsonData.Message); } else { if (currentNum >= 10) { alert("上传图片不能超过10张"); return; } totalNum++; currentNum++; $("#imgNum").html("当前" + currentNum + "张图片"); var imgHtml = ""; imgHtml += "<div class=\"divContent\">"; imgHtml += " <div class=\"divDiv\">"; imgHtml += "<img src=\"http://upload.com" + jsonData.Url + "\" class=\"img\" urlData=\"" + jsonData.Url + "\"/>"; imgHtml += "</div>"; imgHtml += "<img class=\"delImg\" src=\"/Content/Img/del.png\" id=\"" + totalNum + "\">"; imgHtml += "</div>"; $("#imgUrl").append(imgHtml); $("#" + totalNum + "").click(function () { $(this).parent().remove(); currentNum--; $("#imgNum").html("当前" + currentNum + "张图片"); }); } } //swfupload插件上传失败回调事件 function uploadError(file, serverData) { alert("上传失败"); } return { init: function () { _initEvent(); } } }();
本地后端接收文件和参数,并已二进制格式发送给文件服务器。
public ActionResult LocalReceive() { string token = Request["token"]; string service = Request["service"]; HttpPostedFileBase file = Request.Files["FileData"]; string fileName = Path.GetFileName(file.FileName); string upLoadUrl = "http://upload.com/ReceiveFile/Index";//异步上传文件地址 url需要改成本地配自己的域名 string boundry = "----------------------------------" + DateTime.Now.Ticks.ToString("x");//boundary是分隔符 因为上传文件不在使用原有的http协议了。请求内容不再可能以 x = y方式发送了。
//而使用了 分隔符 字段内容 分隔符号 字段内容2 而boundary就是指定分隔符号的标志。 try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(upLoadUrl); request.ContentType = "multipart/form-data;boundary=" + boundry;//设置二进制方式传输 request.Method = "POST"; request.KeepAlive = true; request.Credentials = CredentialCache.DefaultCredentials;//获取或设置请求的身份验证信息。 MemoryStream stream = new MemoryStream(); byte[] line = Encoding.UTF8.GetBytes("\r\n--" + boundry + "\r\n"); #region 传文本参数 Dictionary<string, string> paramDic = new Dictionary<string, string>(); paramDic.Add("Service", service); paramDic.Add("Token", token);//上传注掉 string paramTempalte = "\r\n--" + boundry + "\r\nContent-Disposition: form-data;name=\"{0}\";\r\n\r\n{1}"; foreach (var item in paramDic) { string paramStr = string.Format(paramTempalte, item.Key, item.Value); byte[] paramByte = Encoding.UTF8.GetBytes(paramStr); stream.Write(paramByte, 0, paramByte.Length); } stream.Write(line, 0, line.Length); #endregion #region 传文件 Stream fileReceiveStream = file.InputStream;//测试是否可以合并 byte[] fileByte = new byte[fileReceiveStream.Length]; fileReceiveStream.Read(fileByte, 0, fileByte.Length); fileReceiveStream.Close(); string fileHeadTemplate = "Content-Disposition: form-data;name=\"{0}\";filename=\"{1}\"\r\nContent-Type:application/octet-stream\r\n\r\n"; string fileHeadStr = string.Format(fileHeadTemplate, "FileData", fileName); byte[] fileHeadByte = Encoding.UTF8.GetBytes(fileHeadStr); stream.Write(fileHeadByte, 0, fileHeadByte.Length); stream.Write(fileByte, 0, fileByte.Length); stream.Write(line, 0, line.Length); #endregion #region 结束上传 request.ContentLength = stream.Length; Stream requestStream = request.GetRequestStream(); stream.Position = 0L; stream.CopyTo(requestStream); stream.Close(); requestStream.Close(); #endregion #region 获取返回 HttpWebResponse responseReceive = request.GetResponse() as HttpWebResponse; Stream streamReceive = responseReceive.GetResponseStream(); StreamReader streamReader = new StreamReader(streamReceive, Encoding.UTF8); string content = streamReader.ReadToEnd(); #endregion JavaScriptSerializer js = new JavaScriptSerializer(); UpLoadFileOut upLoadFileOut = js.Deserialize<UpLoadFileOut>(content); return Json(upLoadFileOut); } catch (Exception ex) { return Json(new { Code = "102", Message = "服务器内部错误", Exception = ex.Message }); } }
文件服务器接收参数和文件,验证参数并保存文件。
public ActionResult Index() { string token = Request["token"]; string service = Request["service"]; if (token != "b2ed46cd1bee4e5d816abdb1ec31b0f8" || service != "MyServiceName") { return Json(new { Time = DateTime.Now, Code = "101", Message = "参数错误", Url = "" }); } HttpPostedFileBase file = Request.Files["FileData"]; string fileName = Path.GetFileName(file.FileName); string fileExt = Path.GetExtension(fileName); string dir = "/UpLoadFile/" + DateTime.Now.Year + "/" + DateTime.Now.Month + "/" + DateTime.Now.Day + "/"; Directory.CreateDirectory(Path.GetDirectoryName(Request.MapPath(dir))); string fullDir = dir + GetStreamMD5(file.InputStream) + fileExt; //文件的MD5值也就是文件名,故根据文件完成路径来判断是否重复上传了,若重复则不需保存。 if (!System.IO.File.Exists(Request.MapPath(fullDir))) { file.SaveAs(Request.MapPath(fullDir)); } return Json(new { Time = DateTime.Now, Code = "100", Message = "成功", Url = fullDir }); } /// <summary> /// 计算文件的MD5值 /// </summary> /// <param name="stream"></param> /// <returns></returns> public static string GetStreamMD5(Stream stream) { string strResult = ""; string strHaseData = ""; byte[] arrbyHashValue; System.Security.Cryptography.MD5CryptoServiceProvider oMD5Hasher = new System.Security.Cryptography.MD5CryptoServiceProvider(); arrbyHashValue = oMD5Hasher.ComputeHash(stream); strHaseData = System.BitConverter.ToString(arrbyHashValue); strHaseData = strHaseData.Replace("-", ""); strResult = strHaseData; return strResult; }
欢迎批评指正和交流探讨
DEMO下载地址: http://download.csdn.net/detail/fcydxbd/9710819