html5上傳圖片(二)一解決部分手機拍照上傳圖片轉向問題

来源:http://www.cnblogs.com/xietong/archive/2016/08/05/5741905.html
-Advertisement-
Play Games

本以為解決跨域上傳後沒有問題了,不成想被測試找出一個問題,那就是在手機上拍照上傳後圖片會旋轉。很頭痛,不過沒有辦法,問題還是需要解決的。在查閱了一系列資料後我找到了相應的解決方案,利用exif.js獲取圖片旋轉的方向,然後再轉過來圖片,之後再上傳。這個方案需要修改前面的腳本,同樣的,由於要傳base ...


       本以為解決跨域上傳後沒有問題了,不成想被測試找出一個問題,那就是在手機上拍照上傳後圖片會旋轉。很頭痛,不過沒有辦法,問題還是需要解決的。在查閱了一系列資料後我找到了相應的解決方案,利用exif.js獲取圖片旋轉的方向,然後再轉過來圖片,之後再上傳。這個方案需要修改前面的腳本,同樣的,由於要傳base64字元串,後臺也要做出相應的修改。下麵是我修改後的相應代碼:

  1 (function () {
  2     var imgOperate = {
  3         operateUrl: "更改圖片在資料庫中的狀態地址",
  4         uploadUrl: "代理圖片上傳地址",
  5         DelPicId: '',
  6         ddWidth: 0,
  7         dlWidth:0,
  8         successCount:0,
  9         onload: function () {
 10             this.initImage();
 11         },
 12         initImage: function () {
 13             var et = $('#entrust dd').length;
 14             this.ddWidth = $('#entrust dd').width() + 17;
 15             this.dlWidth = parseInt(et * this.ddWidth + 160);
 16             $('#entrust').css("width", this.dlWidth);
 17             this.BindEvent();
 18         },
 19         BindEvent: function () {
 20             var _this = this;
 21             $("#pic0").on("change", function () {
 22                
 23                 _this.uploadFiles(this);
 24               
 25             });
 26     
 27         },
 28         InserImage:function(urls,dd)
 29         {
 30             $.post(this.operateUrl, { houseid: houseid, operateType: 1, picStr: urls }, function (data) {
 31                 data = eval("(" + data + ")");
 32                 if (data && data.picIds)
 33                 {
 34                     dd.getElementsByTagName("img")[0].setAttribute("housepicid", data.picIds);
 35                 }
 36             });
 37         },
 38         uploadFiles: function (where) {
 39             if (!houseid) { 
 40                 this.ShowMsg("請回到第一步完善相應的信息");
 41                 return;
 42             }
 43             var imgLength = $("#entrust dd").length - 1;
 44             
 45             if (imgLength >= 50)
 46             {
 47                 this.ShowMsg("你的圖片超過了50張,不能再上傳");
 48                 return;
 49             }
 50             if (imgLength + where.files.length > 50)
 51             {
 52                 this.ShowMsg("你選擇的圖片超過了50張,無法上傳,請重新選擇");
 53                 return;
 54             }
 55          
 56 
 57             var _this = this;
 58             var radtime = new Date();
 59             var sid = radtime.getTime();
 60             this.successCount=0;
 61             for (var i = 0; i < where.files.length; i++) {
 62                 var formData = new FormData();
 63                 var file = where.files[i];
 64                 var orientation = 1;
 65       
 66                 if (file.name.indexOf("jpg") > -1) {
 67                     EXIF.getData(file, function () {
 68                         EXIF.getAllTags(this);  
 69                         orientation = EXIF.getTag(this, 'Orientation');
 70                         if (orientation) {
 71                             var reader = new FileReader();
 72                             reader.onload = function (e) {
 73                                 _this.getImgData(e, this.result, orientation, function (data) {
 74 
 75                                     var base64String = data;
 76                                     formData.append("icoimage", base64String);
 77                                     _this.UploadImg(where, formData, sid, i);
 78                                 });
 79                             }
 80                             reader.readAsDataURL(file);
 81                         } else {
 82                             formData.append("icoimage", file);
 83                             _this.UploadImg(where, formData, sid, i);
 84                         }
 85                     });
 86                 } else {
 87                     formData.append("icoimage", file);
 88                     _this.UploadImg(where, formData, sid, i);
 89                 }
 90               
 91               
 92              
 93             }
 94 
 95         },
 96         UploadImg: function (where, formData, sid, i) {
 97             var _this = this;
 98             $.ajax({
 99                 url: this.uploadUrl + '?channel=頻道&sid=' + sid,
100                 type: 'POST',
101                 cache: false,
102                 data: formData,
103                 processData: false,
104                 contentType: false
105             }).success(function (res) {
106                 var imgsrc = res;
107                 if (imgsrc == "-1" || imgsrc == "302" || imgsrc == -1 || imgsrc == 302) {
108                     _this.ShowMsg("上傳失敗,照片超過10M");
109                 } else if (imgsrc.indexOf("http") != -1) {
110                     var dd = document.createElement("dd");
111                     if ($("#entrust dd").length == 1) {
112                         dd.innerHTML = "<div class=\"cver\">封面圖</div><a class=\"close\"></a><img src=\"" + imgsrc + "\" housepicid=\"\">";
113                     } else {
114                         dd.innerHTML = "<a class=\"close\"></a><img src=\"" + imgsrc + "\" housepicid=\"\">";
115                     }
116                     document.getElementById("entrust").appendChild(dd);
117                     _this.dlWidth += _this.ddWidth + 17;
118                     $('#entrust').css("width", _this.dlWidth);
119                     _this.InserImage(imgsrc, dd);
120                     this.successCount++;
121                     _this.ShowMsg("正在上傳第" + i + "張圖片");
122                 }
123                 if (i == where.files.length) {
124                     if (this.successCount > 0) {
125                         _this.ShowMsg("成功上傳" + successCount + ",可繼續上傳新照片");
126                     }
127                 } 
128 
129             })
130         },
131         ShowMsg: function (text, mymethod) {
132             var radtime = new Date();
133             var sid = radtime.getTime();
134             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>";
135 
136             $(msg_div).appendTo("body");
137             var _this = this;
138             setTimeout(function () {
139                 var d = 0.5;
140                 var m = document.getElementById("div_msg"+sid);
141                 m.style.webkitTransition = '-webkit-transform ' + d + 's ease-in, opacity ' + d + 's ease-in';
142                 m.style.opacity = '0';
143                 setTimeout(_this.RemoveNode(m), 500);
144             }, 500);
145         },
146         RemoveNode: function (m) {
147             m.parentNode.removeChild(m);
148         },
149         // @param {string} img 圖片的base64
150         // @param {int} dir exif獲取的方向信息
151         // @param {function} next 回調方法,返回校正方向後的base64
152         getImgData: function (e,img, dir, next) {
153             var _this = this;
154             var image = new Image();
155             image.src = e.target.result;
156     image.onload=function(){
157         var degree=0,drawWidth,drawHeight,width,height;
158         drawWidth=this.naturalWidth;
159         drawHeight=this.naturalHeight;
160         //以下改變一下圖片大小
161         var maxSide = Math.max(drawWidth, drawHeight);
162         if (maxSide > 1024) {
163             var minSide = Math.min(drawWidth, drawHeight);
164             minSide = minSide / maxSide * 1024;
165             maxSide = 1024;
166             if (drawWidth > drawHeight) {
167                 drawWidth = maxSide;
168                 drawHeight = minSide;
169             } else {
170                 drawWidth = minSide;
171                 drawHeight = maxSide;
172             }
173         }
174         var canvas=document.createElement('canvas');
175         canvas.width=width=drawWidth;
176         canvas.height=height=drawHeight; 
177         var context = canvas.getContext('2d');
178         //判斷圖片方向,重置canvas大小,確定旋轉角度,iphone預設的是home鍵在右方的橫屏拍攝方式
179         switch(dir){
180             case 2:
181                 context.translate(width, 0);
182                 context.scale(-1, 1);
183                 break;
184             case 3:
185                 context.translate(width, height);
186                 context.rotate(Math.PI);
187                 break;
188             case 4:
189                 context.translate(0, height);
190                 context.scale(1, -1);
191                 break;
192             case 5:
193                 context.rotate(0.5 * Math.PI);
194                 context.scale(1, -1);
195                 break;
196             case 6:
197                 context.rotate(0.5 * Math.PI);
198                 context.translate(0, -height);
199                 break;
200             case 7:
201                 context.rotate(0.5 * Math.PI);
202                 context.translate(width, -height);
203                 context.scale(-1, 1);
204                 break;
205             case 8:
206                 context.rotate(-0.5 * Math.PI);
207                 context.translate(-width, 0);
208                 break;
209           
210         }
211 
212         context.drawImage(this,0,0,drawWidth,drawHeight);
213         //返回校正圖片
214         next(canvas.toDataURL("image/jpeg",.8));
215     }
216     image.src=img;
217 }
218 
219     }
220 
221     imgOperate.onload();
222     window.imgOperate = imgOperate;
223 
224 })();
225    
前端腳本
 1   public override void ProcessRequest(HttpContext context)
 2         {
 3             //獲取目標站點地址
 4             String target = "圖片伺服器地址";
 5             string sid = context.Request["sid"];
 6             target = string.Format("{0}?city=&channel=頻道&sid={1}&backurl=",target,sid);
 7             string imgText = string.Empty;
 8             if (context.Request.Files.Count == 0 && string.IsNullOrEmpty(imgText=context.Request["icoimage"]))
 9             {
10                 Response.Write("0");
11                 Response.End();
12             }
13 
14             Stream stream = new MemoryStream();
15             string fileName = string.Empty;
16             byte[] bArr = null;
17             if (context.Request.Files.Count > 0)
18             {
19               var  file = context.Request.Files[0];
20               fileName = file.FileName;
21               stream = file.InputStream;
22               bArr = new byte[stream.Length];
23               stream.Read(bArr, 0, bArr.Length);
24               stream.Close();
25             }
26             else {
27                 imgText = HttpUtility.UrlDecode(imgText);
28                 imgText = Regex.Match(imgText, "(?<=,).*").Value;
29                    imgText= imgText.Trim().Replace("%", "").Replace(",", "").Replace(" ", "+");
30                    if (imgText.Length % 4 > 0)
31                    {
32                        imgText = imgText.PadRight(imgText.Length + 4 - imgText.Length % 4, '=');
33                    }
34               bArr=Convert.FromBase64String(imgText);
35             
36                  fileName = "base64.png";
37                
38             }
39                 HttpWebRequest request = WebRequest.Create(target) as HttpWebRequest;
40                 CookieContainer cookieContainer = new CookieContainer();
41                 request.CookieContainer = cookieContainer;
42                 request.AllowAutoRedirect = true;
43                 request.Method = "POST";
44                 request.Headers.Add("Origin", "http://" + context.Request.UrlReferrer.Host);
45                 request.Headers.Add("Accept-Encoding", "gzip, deflate");
46                 request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8");
47                 request.Headers.Add("Upgrade-Insecure-Requests", "1");
48                 request.Referer = context.Request.UrlReferrer.OriginalString;
49                 string boundary = DateTime.Now.Ticks.ToString("X"); // 隨機分隔線
50                 request.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary;
51                 byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
52                 byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
53               
54                 //請求頭部信息 
55                 StringBuilder sbHeader = new StringBuilder(string.Format("Content-Disposition:form-data;name=\"file\";filename=\"{0}\"\r\nContent-Type:application/octet-stream\r\n\r\n",fileName));
56                 byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString());
57 
58                 Stream postStream = request.GetRequestStream();
59                 postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
60                 postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
61                 postStream.Write(bArr, 0, bArr.Length);
62                 postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
63                 postStream.Close();
64                 //發送請求並獲取相應回應數據
65                 HttpWebResponse response = request.GetResponse() as HttpWebResponse;
66                 SetCookie(response,context);
67             
68         
69    
70         }
71 
72 
73       
74         //response是目標伺服器的響應對象,context是返回給瀏覽器的上下文對象
75         void SetCookie(HttpWebResponse response, HttpContext context)
76         {
77             foreach (Cookie cookie in response.Cookies)
78             {
79                 if (cookie.Name!=null&&cookie.Name.StartsWith("Picture"))
80                 {
81                     string result=string.Empty;
82                     if (cookie.Value != null && cookie.Value.StartsWith("http://"))
83                     {
84                         Regex r = new Regex(@"^.*?(?=\|)");
85                         result = r.Match(cookie.Value).Value;
86                     }
87                     else {
88                         result = cookie.Value;
89                     }
90                     context.Response.Write(result);
91                     context.Response.End();
92                 }
93             
94             }
95         }
View Code

      本次遇到的難題主要是解析base64字元串的問題,總是遇到"輸入的不是有效的 Base-64 字元串,因為它包含非 Base-64 字元、兩個以上的填充字"。經過反覆的調整,終於實現了相應的功能。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <script> function lol(type) { if(typeof type == "undefined") { alert("undefined"); } else if(typeof type == "object") { if(new String(type) == "null") ...
  • 最近在這段時間瞭解了下redux,下麵簡單記錄下所得。 redux總結 首先,還是用幾句話簡單概括下redux吧,歡迎拍磚。 redux採用的函數式編程方式,基於單項數據流模式管理應用中的狀態。 一個複雜應用對應一個狀態樹,應用模塊之前共用的狀態都交由該狀態樹負責維護。 只能通過觸發action對象 ...
  • 本文記載boot 導航條組件使用方法 導航條組件 導航條是在您的應用或網站中作為導航頁頭的響應式基礎組件。它們在移動設備上可以摺疊(並且可開可關),且在視口(viewport)寬度增加時逐漸變為水平展開模式。 屏幕解析度變化時,頁面導航呈現不同效果,變小時會出現漢堡包按鈕,將頁面導航部分隱藏,以下拉 ...
  • × 目錄 [1]定義 [2]創建 [3]組成[4]引用 前面的話 javascript中的難點是函數、對象和繼承,前面已經介紹過函數系列。從本系列開始介紹對象部分,本文是該系列的第一篇——初識對象 對象定義 javascript的基本數據類型包括undefined、null、boolean、stri ...
  • 前言 這一章的內容學到了事件隊列和非同步的API。js只是運行在其他應用程式的腳本語言。js即依賴於應用程式,也獨立與應用程式。可以使它可以在多平臺,多種環境上運行。ECMAScript標準中沒有關於併發的說明。這章討論的是一些常用的方法,使用事件和非同步API是js編程的基礎部分。非同步API,有set... ...
  • 寫在前面 1.在客戶端、服務端架構中,HTTP協議是主流通信技術; 2.HTTP協議的無狀態特性,節省帶寬,較少伺服器的負載,緩衝技術具有重要的運用;這裡主要講解在客戶端瀏覽器中angular如何讀寫緩存... 如何實現 1.angular提供了ngCookies模塊來實現讀寫緩存的操作,基於ang ...
  • HTML基本元素(HTML框架、HTML表單、HTML5表單新屬性) ...
  • (1)瞭解背景:歷史、現狀、發展、應用領域、特點 ——要瞭解我要學的這門技術/語言的來龍去脈,尤其是現狀,這樣我們才知道學習它的價值等。 (2)搭建運行/測試環境 ——前端還好,要是後臺語言的話據說光搭建環境有的就需要半天,畢竟這些東西做好了,我們才能看到效果,事半功倍。 (3)編寫Hello Wo ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...