最近開發一個上傳圖片的模塊,傳圖片的接口不支持跨域上傳,並且只支持單張上傳,而我們的產品要求要實現多張上傳。我搞了一個代理頁面,先將圖片傳到代理頁面,然后再通過代理頁面傳到上傳圖片接口。雖然這種方式經過一個代理頁面會增加消耗的時間,但總算解決了跨域上傳的問題。現在粘貼我的代碼如下,前端腳本:
1 (function () { 2 var imgOperate = { 3 operateUrl: "更改圖片在數據庫中的狀態地址", 4 uploadUrl: "代理圖片上傳地址", 5 DelPicId: '', 6 ddWidth: 0, 7 dlWidth:0, 8 onload: function () { 9 this.initImage(); 10 }, 11 initImage: function () { 12 var et = $('#entrust dd').length; 13 this.ddWidth = $('#entrust dd').width() + 17; 14 this.dlWidth = parseInt(et * this.ddWidth + 160); 15 $('#entrust').css("width", this.dlWidth); 16 this.BindEvent(); 17 }, 18 BindEvent: function () { 19 var _this = this; 20 $("#pic0").on("change", function () { 21 22 _this.uploadFiles(this); 23 24 }); 25 26 }, 27 InserImage:function(urls,dd) 28 { 29 $.post(this.operateUrl, { houseid: houseid, operateType: 1, picStr: urls }, function (data) { 30 data = eval("(" + data + ")"); 31 if (data && data.picIds) 32 { 33 dd.getElementsByTagName("img")[0].setAttribute("housepicid", data.picIds); 34 } 35 }); 36 }, 37 uploadFiles: function (where) { 38 39 var imgLength = $("#entrust dd").length - 1; 40 41 if (imgLength >= 50) 42 { 43 this.ShowMsg("你的圖片超過了50張,不能再上傳"); 44 return; 45 } 46 if (imgLength + where.files.length > 50) 47 { 48 this.ShowMsg("你選擇的圖片超過了50張,無法上傳,請重新選擇"); 49 return; 50 } 51 var _this = this; 52 var radtime = new Date(); 53 var _this = this; 54 var sid = radtime.getTime(); 55 for (var i = 0, successCount=0; i < where.files.length; i++) { 56 var formData = new FormData(); 57 58 formData.append("icoimage",where.files[i]); 59 60 $.ajax({ 61 url:this.uploadUrl+ '?channel=頻道&sid=' + sid, 62 type: 'POST', 63 cache: false, 64 data: formData, 65 processData: false, 66 contentType: false 67 }).success(function (res) { 68 var imgsrc = res; 69 if (imgsrc == "-1" || imgsrc == "302" || imgsrc == -1 || imgsrc == 302) { 70 _this.ShowMsg("上傳失敗,照片超過10M"); 71 } else if (imgsrc.indexOf("http")!=-1) { 72 var dd = document.createElement("dd"); 73 if ($("#entrust dd").length == 1) { 74 dd.innerHTML = "<div class=\"cver\">封面圖</div><a class=\"close\"></a><img src=\"" + imgsrc + "\" housepicid=\"\">"; 75 } else { 76 dd.innerHTML = "<a class=\"close\"></a><img src=\"" + imgsrc + "\" housepicid=\"\">"; 77 } 78 document.getElementById("entrust").appendChild(dd); 79 _this.dlWidth += _this.ddWidth + 17; 80 $('#entrust').css("width", _this.dlWidth); 81 _this.InserImage(imgsrc, dd); 82 successCount++; 83 _this.ShowMsg("正在上傳第" + i + "張圖片"); 84 } 85 if (i == where.files.length) { 86 if (successCount > 0) { 87 _this.ShowMsg("成功上傳" + successCount + ",可繼續上傳新照片"); 88 } 89 } else { 90 _this.ShowMsg("上傳失敗"); 91 } 92 93 }) 94 } 95 96 }, 97 ShowMsg: function (text, mymethod) { 98 var radtime = new Date(); 99 var sid = radtime.getTime(); 100 var msg_div = "<div class='zuopenbox' id='div_msg" + sid + "'><div class='opencon_01'><div class='openList'><h3 class='f15' style='margin-bottom: 0; color: #FFFFFF'>" + text + "</h3></div></div></div>"; 101 102 $(msg_div).appendTo("body"); 103 var _this = this; 104 setTimeout(function () { 105 var d = 0.5; 106 var m = document.getElementById("div_msg"+sid); 107 m.style.webkitTransition = '-webkit-transform ' + d + 's ease-in, opacity ' + d + 's ease-in'; 108 m.style.opacity = '0'; 109 setTimeout(_this.RemoveNode(m), 500); 110 }, 500); 111 }, 112 RemoveNode: function (m) { 113 m.parentNode.removeChild(m); 114 } 115 116 } 117 118 imgOperate.onload(); 119 window.imgOperate = imgOperate; 120 121 122 123 })();
代理服務器代碼:
public override void ProcessRequest(HttpContext context) { //獲取目標站點地址 String target = "圖片服務器地址"; string sid = context.Request["sid"]; target = string.Format("{0}?city=&channel=頻道&sid={1}&backurl=",target,sid); if(context.Request.Files.Count>0) { var file = context.Request.Files[0]; HttpWebRequest request = WebRequest.Create(target) as HttpWebRequest; CookieContainer cookieContainer = new CookieContainer(); request.CookieContainer = cookieContainer; request.AllowAutoRedirect = true; request.Method = "POST"; request.Headers.Add("Origin", "http://" + context.Request.UrlReferrer.Host); request.Headers.Add("Accept-Encoding", "gzip, deflate"); request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8"); request.Headers.Add("Upgrade-Insecure-Requests", "1"); request.Referer = context.Request.UrlReferrer.OriginalString; string boundary = DateTime.Now.Ticks.ToString("X"); // 隨機分隔線 request.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary; byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n"); byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); //請求頭部信息 StringBuilder sbHeader = new StringBuilder(string.Format("Content-Disposition:form-data;name=\"file\";filename=\"{0}\"\r\nContent-Type:application/octet-stream\r\n\r\n", file.FileName)); byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString()); //FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); byte[] bArr = new byte[file.InputStream.Length]; file.InputStream.Read(bArr, 0, bArr.Length); file.InputStream.Close(); Stream postStream = request.GetRequestStream(); postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length); postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length); postStream.Write(bArr, 0, bArr.Length); postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); postStream.Close(); //發送請求並獲取相應回應數據 HttpWebResponse response = request.GetResponse() as HttpWebResponse; SetCookie(response,context); } } //response是目標服務器的響應對象,context是返回給瀏覽器的上下文對象 void SetCookie(HttpWebResponse response, HttpContext context) { foreach (Cookie cookie in response.Cookies) { if (cookie.Name!=null&&cookie.Name.StartsWith("img")) { string result=string.Empty; if (cookie.Value != null && cookie.Value.StartsWith("http://")) { Regex r = new Regex(@"^.*?(?=\|)"); result = r.Match(cookie.Value).Value; } else { result = cookie.Value; } context.Response.Write(result); context.Response.End(); } } }
因為圖片服務器返回的地址是種在cookie當中的,因此代理服務器中我將相應cookie的地址接收予以返回。在開發該功能時我遇到了很多問題,圖片接口同事比較忙,無法配合,后來自己模擬相應服務器的接口上傳,才發現代理中並沒有將文件傳上去。經過比較修改,最后才上傳成功。
