.Net平臺移動端實現圖像上傳、壓縮及預覽功能詳解

最近再給公司做移動端開發圖像上傳裁剪壓縮以及預覽的功能,給大家分享一點心得,首先給大家看一下最終實現效果:

首先是前端把圖片轉化成base64格式然後通過ajax異步發送到服務器

html部分

<div style="background-color:#fff;margin-top:-5px;padding:0px 8px;">
 <img οnclick="DeleteImage(this)" id="ImgShow0" class="ImgPreHidden" src="" alt="" />
 <img οnclick="DeleteImage(this)" id="ImgShow1" class="ImgPreHidden" src="" alt="" />
 <img οnclick="DeleteImage(this)" id="ImgShow2" class="ImgPreHidden" src="" alt="" />
 <img οnclick="DeleteImage(this)" id="ImgShow3" class="ImgPreHidden" src="" alt="" />
 <img οnclick="DeleteImage(this)" id="ImgShow4" class="ImgPreHidden" src="" alt="" />
 <image id="ImgUploadButtom" οnclick="$('#ImgUpload').click()" style="width:80px;height:80px;margin-bottom:2px;" src="../../../../Content/image/camera.png" />
 <input  type="file" id="ImgUpload" style="display:none;" />
</div>

javascript部分

使用canvas對象對圖片進行壓縮,使用exif.js解決部分手機拍照之後圖片旋轉問題

$("#ImgUpload").on("change", headPortraitListener);
/*頭像上傳監聽*/
function headPortraitListener(e) {
	var ImgShowI = 0;
	for (var i = 1; i <= 4; i++) {
		if ($("#ImgShow" + i).attr("src") == "") {
			ImgShowI = i;
			break;
		}
	}
	if (ImgShowI == 0) {
		_layer.msg("最多隻能上傳4張圖片");
		return;
	}

	var img = document.getElementById("ImgShow" + i);
	var img0 = document.getElementById("ImgShow0");
	if (window.FileReader) {
		var file = e.target.files[0];
		 EXIF.getData(file, function () {
			Orientation = EXIF.getTag(this, 'Orientation');
		});
		var reader = new FileReader();
		if (file && file.type.match('image.*')) {
			reader.readAsDataURL(file);
		} else {
			img.setAttribute('class', 'ImgShow ImgPreHidden');
			img.setAttribute('src', '');
		}
		reader.onloadend = function (e) {
			img0.setAttribute('src', reader.result);
		}
		img0.onload = function () {
			var imgWidth = this.width,
							imgHeight = this.height;
			console.log(this);
			if (imgWidth > imgHeight && imgWidth > 1000) {
				imgWidth = 1000;
				imgHeight = Math.ceil(1000 * this.height / this.width);
			} else if (imgWidth < imgHeight && imgHeight > 1334) {
				imgWidth = Math.ceil(1334 * this.width / this.height);
				imgHeight = 1334;
			}

			var canvas = document.createElement("canvas"),
						ctx = canvas.getContext('2d');
			canvas.width = imgWidth;
			canvas.height = imgHeight;
			if (Orientation && Orientation != 1) {
				switch (Orientation) {
					case 6:
						canvas.width = imgHeight;
						canvas.height = imgWidth;
						ctx.rotate(Math.PI / 2);
						ctx.drawImage(this, 0, -imgHeight, imgWidth, imgHeight);
						break;
					case 3:
						ctx.rotate(Math.PI);
						ctx.drawImage(this, -imgWidth, -imgHeight, imgWidth, imgHeight);
						break;
					case 8:
						canvas.width = imgHeight;
						canvas.height = imgWidth;
						ctx.rotate(3 * Math.PI / 2);
						ctx.drawImage(this, -imgWidth, 0, imgWidth, imgHeight);
						break;
				}
			} else {
				ctx.drawImage(this, 0, 0, imgWidth, imgHeight);
			}

			UploadImage(img, canvas.toDataURL("image/jpeg", 0.8));
		}
	}
}
function DeleteImage(e) {
	$(e).attr('class', 'ImgPreHidden');
	$(e).attr('src', '');
	$("#ImgUploadButtom").show();
}
function UploadImage(img, base64Image) {
	var postData = {};
	postData["Bill_Id"] = $("#ID").val();
	postData["Base64Image"] = base64Image;
	AjaxJson("/ExtensionApp/ComplaintMailbox/UploadImage", "json=" + JSON.stringify(postData), function (result) {
		if (result.status == "1") {
			img.setAttribute('src', base64Image);
			img.setAttribute('class', 'ImgShow ImgPreShow');
			IsImage();
		} else {
			_layer.msg(result.message);
		}
	})
}
function IsImage() {
	var ImgShowI = 0;
	for (var i = 1; i <= 4; i++) {
		if ($("#ImgShow" + i).attr("src") == "") {
			ImgShowI = i;
			break;
		}
	}
	if (ImgShowI == 0) {
		$("#ImgUploadButtom").hide();
		return;
	}
}

C#後端部分

public ActionResult UploadImage(string json)
{
	SH.Entity.CommonModule.CommonResult<Hashtable> result = new SH.Entity.CommonModule.CommonResult<Hashtable>();
	try
	{
		
		Base_Image entity = json.JsonToEntity<Base_Image>();
		var Image = SH.Utilities.Base.Media.ImageExt.Compression(entity.Base64Image, 1000);
		entity.Id = Guid.NewGuid().ToString();
		using (MiniPoco.Database db = new MiniPoco.Database())
		{
			var data_type = entity.Base64Image.Split(',');
			string Ext = data_type[0].Split('/')[1].Split(';')[0];

			string _Url = "\\WeChat\\" + DateTime.Now.ToString("yyyy-MM");
			entity.CreateDate = DateTime.Now;
			string fileName = entity.Id + "." + Ext;
			entity.Status = 0;
			entity.Url = _Url + "\\" + fileName;

			string ImageFilePath = "\\\\網盤地址" + _Url;
			if (System.IO.Directory.Exists(ImageFilePath) == false)//如果不存在就創建文件夾
			{
				System.IO.Directory.CreateDirectory(ImageFilePath);
			}
			string ImagePath = ImageFilePath + "\\" + fileName;//定義圖片名稱

			Image.Save(ImagePath); //保存圖片到服務器,然後獲取路徑  
			db.Insert<Base_Image>(entity);
			db.Save();
			result.status = "1";
			result.message = entity.Id;

			return Content(result.ToJson());
		}
	}
	catch (Exception ex)
	{
		result.status = "0";
		result.message = ex.Message;
		return Content(result.ToJson());
	}
}

使用PhotoSwipe實現圖片的預覽功能

引入必要的css和js

<!-- Core CSS file -->
<link href="../../../../Content/js/plugins/PhotoSwipe/photoswipe.css" rel="stylesheet" type="text/css" />
<!-- Skin CSS file (styling of UI - buttons, caption, etc.)
     In the folder of skin CSS file there are also:
     - .png and .svg icons sprite, 
     - preloader.gif (for browsers that do not support CSS animations) -->
<link href="../../../../Content/js/plugins/PhotoSwipe/default-skin/default-skin.css" rel="stylesheet" type="text/css" />
<!-- Core JS file -->
<script src="../../../../Content/js/plugins/PhotoSwipe/photoswipe.min.js" type="text/javascript"></script>
<!-- UI JS file -->
<script src="../../../../Content/js/plugins/PhotoSwipe/photoswipe-ui-default.min.js" type="text/javascript"></script>

html部分

<div id="layer-photos-demo" class="line-div" style="margin-top:5px;">
	<img οnclick="openPhotoSwipe(1)" id="ImgShow1" class="ImgPreHidden" layer-src="" src="" alt="" />
	<img οnclick="openPhotoSwipe(2)" id="ImgShow2" class="ImgPreHidden" layer-src="" src="" alt="" />
	<img οnclick="openPhotoSwipe(3)" id="ImgShow3" class="ImgPreHidden" layer-src="" src="" alt="" />
	<img οnclick="openPhotoSwipe(4)" id="ImgShow4" class="ImgPreHidden" layer-src="" src="" alt="" />
</div>

<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    <!-- Background of PhotoSwipe. 
         It's a separate element, as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>
    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">
        <!-- Container that holds slides. PhotoSwipe keeps only 3 slides in DOM to save memory. -->
        <div class="pswp__container">
            <!-- don't modify these 3 pswp__item elements, data is added later on -->
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--active pswp__ui--fit">
            <div class="pswp__top-bar">
                <!--  Controls are self-explanatory. Order can be changed. -->
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close(Esc)"></button>
                <!-- Preloader demo https://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
          </div>
        </div>
</div>

javascript部分

var PhotoSwipe_items = [
{
	src: '/GetImage?Id=95b5e811-3796-4841-9960-d6d03815baea.jpeg',
	w: 1000,
	h: 750
		},
{
	src: '/GetImage?Id=bb128132-0e9d-4bf7-b68b-aedb89d8d8b2.jpeg',
	w: 1000,
	h: 750
}];

var openPhotoSwipe = function (i) {
	var pswpElement = document.querySelectorAll('.pswp')[0];

	// define options (if needed)
	var options = {
		// history & focus options are disabled on CodePen        
		history: false,
		focus: false,
		index:i-1,
		showAnimationDuration: 0,
		hideAnimationDuration: 0

	};
	var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, PhotoSwipe_items, options);
	gallery.init();
};

給大家看一下圖像壓縮前和壓縮後的對比

壓縮前

壓縮後

最後補充一下圖片壓縮功能的代碼

public static Image Compression(string Base64String, int width)
{
	long quality = 90;//壓縮質量0-100之間 數值越大質量越高

	string ImageType = Base64String.Split(',')[0];
	string temp = Base64String.Split(',')[1];
	temp = temp.Replace(" ", "+");
	int mod4 = temp.Length % 4;
	if (mod4 > 0)
	{
		temp += new string('=', 4 - mod4);
	}
	byte[] btsdata = Convert.FromBase64String(temp);
	MemoryStream ms = new MemoryStream(btsdata);
	Image img = Image.FromStream(ms);

	int height = (int)img.Height * width / img.Width;
	Bitmap _bitmap = new Bitmap(width, height);
	Graphics _graphics = Graphics.FromImage(_bitmap);
	//設置圖片質量
	_graphics.InterpolationMode = InterpolationMode.Low;
	_graphics.SmoothingMode = SmoothingMode.None;
	//繪製圖片
	_graphics.Clear(Color.Transparent);
	_graphics.DrawImage(img, 0, 0, _bitmap.Width, _bitmap.Height);
	//壓縮
	ImageCodecInfo CodecInfo = GetEncoder(img.RawFormat);
	System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
	EncoderParameters myEncoderParameters = new EncoderParameters(1);
	EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, quality);
	myEncoderParameters.Param[0] = myEncoderParameter;
	//保存
	using (MemoryStream memorystream = new MemoryStream())
	{
		_bitmap.Save(memorystream, CodecInfo, myEncoderParameters);
		myEncoderParameters.Dispose();
		myEncoderParameter.Dispose();

		_graphics.Dispose();
		img.Dispose();
		_bitmap.Dispose();

		return BytesToImage(memorystream.ToArray());
	}

}
private static Image BytesToImage(byte[] buffer)
{
	MemoryStream ms = new MemoryStream(buffer);
	Image image = System.Drawing.Image.FromStream(ms);
	return image;
}

private static ImageCodecInfo GetEncoder(ImageFormat format)
{
	ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
	foreach (ImageCodecInfo codec in codecs)
	{
		if (codec.FormatID == format.Guid)
		{ return codec; }
	}
	return null;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章