之前寫過上傳組件,見 打造 html5 文件上傳組件,實現進度顯示及拖拽上傳,兼容IE6+及其它標準瀏覽器,對付通常的上傳沒有問題,不過若是是上傳圖片,且須要預覽的話,就力有不逮了,趁着閒暇時間,給上傳組件添加了單獨的圖片上傳UI,支持圖片預覽和縮放(經過調整圖片的大小以實現圖片壓縮)。javascript
效果如上圖。因爲瀏覽器不一樣,壓縮效果各有不一樣,一個1.1MB、分辨率爲 1920x1200 的圖片,分辨率縮放爲 1024x640 ,IE11上傳後爲199KB,Chrome45上傳後爲277KB,Firefox41上傳後爲360KB。css
html代碼,導入樣式及js上傳組件,定義上傳按鈕及視圖:html
<link href="../css/uploader-image.css" rel="stylesheet" type="text/css" /> <div> <a id="upload-target" class="x-button">添加圖片並上傳</a> </div> <div id="upload-view"></div> <script type="text/javascript" src="../Q.Uploader.image.all.js"></script>
js組件調用:html5
var uploader = new Q.Uploader({ url: "api/upload.ashx", target: document.getElementById("upload-target"), view: document.getElementById("upload-view"), //auto: false, //圖片縮放 scale: { //要縮放的圖片格式 types: ".jpg", //最大圖片大小(width|height) maxWidth: 1024 } }); //uploader.start();
通常無需更改後臺代碼,但若是使用了圖片縮放(壓縮),Firefox、Chrome 較早的版本上傳後,後臺可能會獲取不到文件名,須要略微處理一下。以asp.net爲例:java
HttpRequest request = context.Request; int c = request.Files.Count; //接收上傳的數據並保存到服務器 for (int i = 0; i < c; i++) { HttpPostedFile file = request.Files[i]; //爲兼容一些較早的瀏覽器,此處優先使用上傳組件傳遞的文件名 string fileName = request["fileName"]; if (string.IsNullOrEmpty(fileName)) fileName = System.IO.Path.GetFileName(file.FileName); string path = context.Server.MapPath("~/upload/" + fileName); file.SaveAs(path); }
參見 打造 html5 文件上傳組件,實現進度顯示及拖拽上傳,兼容IE6+及其它標準瀏覽器git
IE10+等瀏覽器使用html5 api,其它瀏覽器使用濾鏡預覽。須要注意的是,IE8+因爲安全性考慮,會獲取不到文件真實地址,須要特殊處理一下。github
//生成圖片預覽地址(html5) function readAsURL(file, callback) { var URL = window.URL || window.webkitURL; if (URL) return callback(URL.createObjectURL(file)); if (window.FileReader) { var fr = new FileReader(); fr.onload = function (e) { callback(e.target.result); }; fr.readAsDataURL(file); } else if (file.readAsDataURL) { callback(file.readAsDataURL()); } } //圖片預覽 function previewImage(box, task, callback) { var input = task.input, file = task.file || (input.files ? input.files[0] : undefined); if (file) { //IE10+、Webkit、Firefox etc readAsURL(file, function (src) { if (src) box.innerHTML = '<img src="' + src + '" />'; callback && callback(src); }); } else if (input) { var src = input.value; if (!src || /^\w:\\fakepath/.test(src)) { input.select(); //解決ie報拒絕訪問的問題 parent.document.body.focus(); //獲取圖片真實地址 if (document.selection) src = document.selection.createRange().text; } if (src) { box.innerHTML = '<img src="' + src + '" />'; try { if (browser_ie > 6) box.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='scale',src='" + src + "')"; } catch (e) { } } callback && callback(src); } }
原理是先經過canvas調整圖片大小,生成base64數據,而後再經過html5 api (Blob) 轉換爲二進制對象上傳。web
//將dataURL轉爲Blob對象,以用於ajax上傳 function dataURLtoBlob(base64, mimetype) { var ds = base64.split(','), data = atob(ds[1]), arr = []; for (var i = 0, len = data.length; i < len; i++) { arr[i] = data.charCodeAt(i); } if (Blob) return new Blob([new Uint8Array(arr)], { type: mimetype }); var builder = new BlobBuilder(); builder.append(arr); return builder.getBlob(mimetype); } //圖片縮放 function scaleImage(src, mimetype, ops, callback) { var image = new Image(); image.src = src; image.onload = function () { var width = image.width, height = image.height, maxWidth = ops.maxWidth, maxHeight = ops.maxHeight, hasWidthScale = maxWidth && width > maxWidth, hasHeightScale = maxHeight && height > maxHeight, hasScale = hasWidthScale || hasHeightScale; //無需壓縮 if (!hasScale) return callback && callback(false); //根據寬度縮放 if (hasWidthScale) { width = maxWidth; height = Math.floor(image.height * width / image.width); } //根據高度縮放 if (hasHeightScale) { height = maxHeight; width = Math.floor(image.width * height / image.height); } var canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"); canvas.width = width; canvas.height = height; ctx.drawImage(image, 0, 0, width, height); callback && callback(canvas.toDataURL(mimetype), mimetype); }; }
其它參見源碼及示例代碼。ajax
asp.net 或其它後臺示例代碼canvas
若是本文或本項目對您有幫助的話,請不吝點個贊。歡迎交流!