<!DOCTYPE html > <html> <head> <title>通过Canvas及File API缩放并上传图片</title> <script src="/Scripts/Jquery/jquery-1.8.3.min.js" type="text/javascript"></script> <script src="/Scripts/MegaPixImage/MegaPixImage.js" type="text/javascript"></script> <script type="text/javascript" language="javascript"> function sendImage() { // 获取 canvas DOM 对象 var canvas = document.getElementById("myCanvas"); // 获取Base64编码后的图像数据,格式是字符串 // "data:image/png;base64,"开头,需要在客户端或者服务器端将其去掉,后面的部分可以直接写入文件。 var dataurl = canvas.toDataURL("image/png"); // 为安全 对URI进行编码 // data%3Aimage%2Fpng%3Bbase64%2C 开头 var imagedata = encodeURIComponent(dataurl); //imagedata = imagedata.replace(‘data:image/png;base64,‘, ‘‘); var url = "/APPCommon/SavePostCanvasImage"; // 因为是string,所以服务器需要对数据进行转码,写文件操作等。 // 个人约定,所有http参数名字全部小写 console.log(dataurl); console.log(imagedata); var data = { imagename: "myImage.png", imagedata: imagedata }; jQuery.ajax({ url: url, data: data, type: "POST", // 期待的返回值类型 dataType: "json", complete: function (xhr, result) { console.log(xhr.responseText); var $tip2 = $("#tip2"); if (!xhr) { $tip2.text(‘网络连接失败!‘); return false; } var text = xhr.responseText; if (!text) { $tip2.text(‘网络错误!‘); return false; } var json = eval("(" + text + ")"); if (!json) { $tip2.text(‘解析错误!‘); return false; } else { $tip2.text(json.Result); } } }); }; </script> </head> <body> <div> <input type="file" capture="camera" accept="image/*" id="cameraInput" name="cameraInput" class="sign_file" /> <canvas id="myCanvas"></canvas> <button id="btnsend" onclick="sendImage()">上 传</button> <div> <label id="tip2"> </label> </div> </div> <script type="text/javascript" language="javascript"> var fileInput = document.getElementById(‘cameraInput‘); fileInput.onchange = function () { var file = fileInput.files[0]; var mpImg = new MegaPixImage(file); var resCanvas1 = document.getElementById(‘myCanvas‘); var _max = 320; mpImg.render(resCanvas1, { maxHeight: _max }); // var resCanvas2 = document.getElementById(‘resultCanvas2‘); // mpImg.render(resCanvas2, { // maxWidth: 300, // maxHeight: 300, // orientation: 6 // }); }; </script> </body> </html>
MegaPixImage.js
/** * Mega pixel image rendering library for iOS6 Safari * * Fixes iOS6 Safari‘s image file rendering issue for large size image (over mega-pixel), * which causes unexpected subsampling when drawing it in canvas. * By using this library, you can safely render the image with proper stretching. * * Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com> * Released under the MIT license */ (function () { /** * Detect subsampling in loaded image. * In iOS, larger images than 2M pixels may be subsampled in rendering. */ function detectSubsampling(img) { var iw = img.naturalWidth, ih = img.naturalHeight; if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image var canvas = document.createElement(‘canvas‘); canvas.width = canvas.height = 1; var ctx = canvas.getContext(‘2d‘); ctx.drawImage(img, -iw + 1, 0); // subsampled image becomes half smaller in rendering size. // check alpha channel value to confirm image is covering edge pixel or not. // if alpha value is 0 image is not covering, hence subsampled. return ctx.getImageData(0, 0, 1, 1).data[3] === 0; } else { return false; } } /** * Detecting vertical squash in loaded image. * Fixes a bug which squash image vertically while drawing into canvas for some images. */ function detectVerticalSquash(img, iw, ih) { var canvas = document.createElement(‘canvas‘); canvas.width = 1; canvas.height = ih; var ctx = canvas.getContext(‘2d‘); ctx.drawImage(img, 0, 0); var data = ctx.getImageData(0, 0, 1, ih).data; // search image edge pixel position in case it is squashed vertically. var sy = 0; var ey = ih; var py = ih; while (py > sy) { var alpha = data[(py - 1) * 4 + 3]; if (alpha === 0) { ey = py; } else { sy = py; } py = (ey + sy) >> 1; } var ratio = (py / ih); return (ratio === 0) ? 1 : ratio; } /** * Rendering image element (with resizing) and get its data URL */ function renderImageToDataURL(img, options, doSquash) { var canvas = document.createElement(‘canvas‘); renderImageToCanvas(img, canvas, options, doSquash); return canvas.toDataURL("image/jpeg", options.quality || 0.8); } /** * Rendering image element (with resizing) into the canvas element */ function renderImageToCanvas(img, canvas, options, doSquash) { var iw = img.naturalWidth, ih = img.naturalHeight; var width = options.width, height = options.height; var ctx = canvas.getContext(‘2d‘); ctx.save(); transformCoordinate(canvas, ctx, width, height, options.orientation); var subsampled = detectSubsampling(img); if (subsampled) { iw /= 2; ih /= 2; } var d = 1024; // size of tiling canvas var tmpCanvas = document.createElement(‘canvas‘); tmpCanvas.width = tmpCanvas.height = d; var tmpCtx = tmpCanvas.getContext(‘2d‘); var vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1; var dw = Math.ceil(d * width / iw); var dh = Math.ceil(d * height / ih / vertSquashRatio); var sy = 0; var dy = 0; while (sy < ih) { var sx = 0; var dx = 0; while (sx < iw) { tmpCtx.clearRect(0, 0, d, d); tmpCtx.drawImage(img, -sx, -sy); ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh); sx += d; dx += dw; } sy += d; dy += dh; } ctx.restore(); tmpCanvas = tmpCtx = null; } /** * Transform canvas coordination according to specified frame size and orientation * Orientation value is from EXIF tag */ function transformCoordinate(canvas, ctx, width, height, orientation) { switch (orientation) { case 5: case 6: case 7: case 8: canvas.width = height; canvas.height = width; break; default: canvas.width = width; canvas.height = height; } switch (orientation) { case 2: // horizontal flip ctx.translate(width, 0); ctx.scale(-1, 1); break; case 3: // 180 rotate left ctx.translate(width, height); ctx.rotate(Math.PI); break; case 4: // vertical flip ctx.translate(0, height); ctx.scale(1, -1); break; case 5: // vertical flip + 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.scale(1, -1); break; case 6: // 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.translate(0, -height); break; case 7: // horizontal flip + 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.translate(width, -height); ctx.scale(-1, 1); break; case 8: // 90 rotate left ctx.rotate(-0.5 * Math.PI); ctx.translate(-width, 0); break; default: break; } } /** * MegaPixImage class */ function MegaPixImage(srcImage) { if (window.Blob && srcImage instanceof Blob) { var img = new Image(); var URL = window.URL && window.URL.createObjectURL ? window.URL : window.webkitURL && window.webkitURL.createObjectURL ? window.webkitURL : null; if (!URL) { throw Error("No createObjectURL function found to create blob url"); } img.src = URL.createObjectURL(srcImage); this.blob = srcImage; srcImage = img; } if (!srcImage.naturalWidth && !srcImage.naturalHeight) { var _this = this; srcImage.onload = function () { var listeners = _this.imageLoadListeners; if (listeners) { _this.imageLoadListeners = null; for (var i = 0, len = listeners.length; i < len; i++) { listeners[i](); } } }; this.imageLoadListeners = []; } this.srcImage = srcImage; } /** * Rendering megapix image into specified target element */ MegaPixImage.prototype.render = function (target, options) { if (this.imageLoadListeners) { var _this = this; this.imageLoadListeners.push(function () { _this.render(target, options) }); return; } options = options || {}; var imgWidth = this.srcImage.naturalWidth, imgHeight = this.srcImage.naturalHeight, width = options.width, height = options.height, maxWidth = options.maxWidth, maxHeight = options.maxHeight, doSquash = !this.blob || this.blob.type === ‘image/jpeg‘; if (width && !height) { height = (imgHeight * width / imgWidth) << 0; } else if (height && !width) { width = (imgWidth * height / imgHeight) << 0; } else { width = imgWidth; height = imgHeight; } if (maxWidth && width > maxWidth) { width = maxWidth; height = (imgHeight * width / imgWidth) << 0; } if (maxHeight && height > maxHeight) { height = maxHeight; width = (imgWidth * height / imgHeight) << 0; } var opt = { width: width, height: height }; for (var k in options) opt[k] = options[k]; var tagName = target.tagName.toLowerCase(); if (tagName === ‘img‘) { target.src = renderImageToDataURL(this.srcImage, opt, doSquash); } else if (tagName === ‘canvas‘) { renderImageToCanvas(this.srcImage, target, opt, doSquash); } if (typeof this.onrender === ‘function‘) { this.onrender(target); } }; /** * Export class to global */ if (typeof define === ‘function‘ && define.amd) { define([], function () { return MegaPixImage; }); // for AMD loader } else { this.MegaPixImage = MegaPixImage; } })();
后台对post请求处理:
[HttpPost] public ActionResult SavePostCanvasImage(string imageData) { var ResObj = new ResWithObj<string, UploadImgInfo> { IsResult = false, Result = string.Empty }; try { var config = WebConfigs.GetConfig(); string _SavePath = Server.MapPath(config.SavePath); string fileNameWitPath = _SavePath + DateTime.Now.ToString().Replace("/", "-").Replace(" ", "- ").Replace(":", "") + ".png"; // 去除开头不合理的数据 data:image/png;base64, imageData = imageData.Substring(30); string img = HttpUtility.UrlDecode(imageData); //保存字节流 System.IO.FileStream fs = new System.IO.FileStream(fileNameWitPath, System.IO.FileMode.Create); System.IO.BinaryWriter bw = new System.IO.BinaryWriter(fs); byte[] data = Convert.FromBase64String(img); bw.Write(data); bw.Close(); ResObj.IsResult = true; ResObj.Result = "上传成功"; } catch (Exception ex) { ResObj.IsResult = false; ResObj.Result = ex.Message; } return Content(JsonConvert.SerializeObject(ResObj)); }