[javascript]檔案上傳以及圖片縮圖成指定的解析度範例

  • 3242
  • 0

[javascript]檔案上傳以及圖片縮圖成指定的解析度範例

檔案上傳的時候,大多還要縮圖,以下是簡易範例:
Html:使用input type=file的fileupload1元件來做上傳,用隱藏欄位AdImage來做調整解析度的圖片的暫存區,用隱藏欄位AdName來當成新上傳檔案的檔案名稱,用div+img來顯示新上傳的圖片或是顯示從db讀出來的圖片(base64字串的圖片)

<div class="row">
	@using (Html.BeginForm("Edit", "AdUpdate", FormMethod.Post, new { @class = "form-horizontal", role = "form", id = "PostForm" }))
	{
		@Html.AntiForgeryToken()
		<input type="hidden" id="AdNum" name="AdNum" value="@ViewBag.AdNum">
		<input type="hidden" id="AdImage" name="AdImage">
		<input type="hidden" id="AdName" name="AdName">
		<div class="col-md-12">
			<div class="card" style="width:940px;">
				<div class="card-body">
					<h4>上方廣告圖片:<span id="fileName">@ViewBag.AdName</span></h4>
					<div class="row mt-4 mb-3">
						<div class="col-md-12">
							<div id="photo" class="align-left" style="width:905px;height:160px; background:#ccc;">
								<img src="@ViewBag.AdImage" />
							</div>
						</div>
					</div>
					<div class="row mt-4 mb-3" id="myTabContent">
						<div class="col-md-6">
							<div class="alert alert-danger alert-dismissable">
								<span style="color: #880000">圖片檔,寬限為905px,高限為160px。</span>
							</div>
						</div>
					</div>

					<div class="row mt-4 mb-3">
						<div class="col-md-2 col-md-offset-4">
							<label class="btn btn-success btn-file">
								<i class="fa fa-lg fa-folder-open"></i>&nbsp;<span>選擇檔案</span>
								<input type="file" id="fileUpload1" name="fileUpload1" style="display: none;">
							</label>
						</div>
						<div class="col-md-2" id="updateBtn">
							<label class="btn btn-warning" onclick="doUpdate('AdImage', 'AdName', 'fileName','PostForm')">
								<i class="fa fa-lg fa-upload"></i>&nbsp;<span>上傳</span>
							</label>
						</div>
						<div class="col-md-2">
							<label class="btn btn-block" onclick="location.reload()">
								<i class="fa fa-lg fa-close"></i>&nbsp;<span>取消</span>
							</label>
						</div>
					</div>
				</div>
			</div>
		</div>
	}
</div>


javascript端於document.ready先幫file upload元件加入onchange事件:SetFileUploadOnChangeEvent()

$(document).ready(function () {
	//設定file upload的 onchange event
	//addEventListener一定要搭配document.getElementById抓物件,用jquery $("#id")的方式抓物件不行
	document.getElementById("fileUpload1").addEventListener("change", function () {
		SetFileUploadOnChangeEvent(this.id, 'photo', 'AdImage', 'fileName', 905, 160);
	}, false);
});


以下是fileupload元件的change事件的function細節:SetFileUploadOnChangeEvent()
會先用imgCheck()檢查使用者上傳的圖片是否為jpg, png, ....
接著會用imgReSize()調整解析度
最後會將縮圖之後的圖片顯示在div+img

//****設定file upload的 onchange event****
//fileUploadId:上傳檔案的元件的id, imageHolderId:載入圖片的div,
//adImageId: base64字串的圖片, labelfileNameId: 顯示圖檔名稱的label的id
//labelfileNameId: 顯示檔案名稱的label的id
//Max_Width: 圖片的寬度, Max_Height:圖片的高度
function SetFileUploadOnChangeEvent(fileUploadId, imageHolderId, adImageId, labelfileNameId,
	Max_Width, Max_Height) {

	//檢查圖片格式
	//alert(fileUploadId);
	var errorMsg = imgCheck(fileUploadId);
	if (errorMsg.length > 0) {
		swal(errorMsg, "", "error");
		return;
	}
	//alert(typeof (FileReader));
	//確認有上傳檔案
	if (document.getElementById(fileUploadId).files.length != 0) {
		var image_holder = $("#" + imageHolderId);
		var AdImage = $("#" + adImageId);

		var reader = new FileReader();

		reader.onload = function (e) {
			imgReSize(e.target.result, imageHolderId, AdImage, fileUploadId,
				Max_Width, Max_Height, labelfileNameId);
		}
		image_holder.show();
		//alert('image_holder.show()');
		var fName = $("#" + fileUploadId)[0].files[0].name;
		//alert(fName);
		//var fSize = $(this)[0].files[0].size;
		$("#" + labelfileNameId).text(fName);

		// $("#fileSize").text(Math.round(fSize / 1024));
		reader.readAsDataURL($("#" + fileUploadId)[0].files[0]);

	} else {
		//alert(1000);
		alert("This browser does not support FileReader.");
	}
	//alert(2000);
	//});
}
//檢查上傳格式必須為png, jpg, jpeg
function imgCheck(fileUploadId) {
	var errMsg = '';
	//var ext = $("#fileUpload1").val().split('.').pop().toLowerCase();
	var ext = $("#" + fileUploadId).val().split('.').pop().toLowerCase();
	if ($.inArray(ext, ['png', 'jpg', 'jpeg']) == -1) {
		errMsg = '請上傳正確的圖片格式';
		$("#" + fileUploadId).val('');
	}
	return errMsg;
}
function imgReSize(source, imageHolderId, B64, fileUploadId, Max_Width, Max_Height, labelfileNameId) {
	var img = document.createElement("img");
	//alert('start resize');
	img.src = source;
	//影像RESIZE
	img.addEventListener('load', function () {
		var canvas = document.createElement("canvas");
		var ctx = canvas.getContext("2d");
		ctx.drawImage(img, 0, 0);

		var MAX_WIDTH = Max_Width;
		var MAX_HEIGHT = Max_Height;
		var width = img.width;
		var height = img.height;

		//檢查圖片大小
		if (width != MAX_WIDTH || height != MAX_HEIGHT) {
			
			swal({
				title: "圖片不符合格式:" + MAX_WIDTH + " * " + MAX_HEIGHT + " px,確認繼續上傳?",
				type: "warning",
				showConfirmButton: true,
				showCancelButton: true,
				confirmButtonText: "Yes",
				cancelButtonText: "No",
				closeOnConfirm: true,
				closeOnCancel: true
			}, function (isConfirm) {
				if (isConfirm) {
					//確定繼續上傳
				}
				else {
					//中止上傳
					$("#" + fileUploadId + "").val('');
					var image_holder = $("#" + imageHolderId);
					image_holder.empty();
					$("#" + labelfileNameId).text('');
					return;
				}
			});
			
		}
		
		if (width > height) {
			if (width > MAX_WIDTH) {
				height *= MAX_WIDTH / width;
				width = MAX_WIDTH;
			}
		} else {
			if (height > MAX_HEIGHT) {
				width *= MAX_HEIGHT / height;
				height = MAX_HEIGHT;
			}
		}
		
		var ctx = canvas.getContext("2d");
		var Width = Max_Width;//預設網頁顯示圖片寬度
		var exifOrientation = '';
		// Check orientation in EXIF metadatas
		EXIF.getData(img, function () {
			var allMetaData = EXIF.getAllTags(this);
			exifOrientation = allMetaData.Orientation;
			//val orientation = ExifInterface(file.absolutePath).getAttribute(ExifInterface.TAG_ORIENTATION)
			console.log('Exif orientation: ' + exifOrientation);
		});
		//alert(333);
		// set proper canvas dimensions before transform & export
		if (jQuery.inArray(exifOrientation, [5, 6, 7, 8]) > -1) {
			canvas.width = height;
			canvas.height = width;
			//動態修改預設網頁顯示圖片寬度,讓高度在框內
			Width = Max_Height * (height / width);
		} else {
			canvas.width = width;
			canvas.height = height;
		}

		// transform context before drawing image
		switch (exifOrientation) {
			case 2:
				ctx.transform(-1, 0, 0, 1, width, 0);
				break;
			case 3:
				ctx.transform(-1, 0, 0, -1, width, height);
				break;
			case 4:
				ctx.transform(1, 0, 0, -1, 0, height);
				break;
			case 5:
				ctx.transform(0, 1, 1, 0, 0, 0);
				break;
			case 6:
				ctx.transform(0, 1, -1, 0, height, 0);
				break;
			case 7:
				ctx.transform(0, -1, -1, 0, height, width);
				break;
			case 8:
				ctx.transform(0, -1, 1, 0, 0, width);
				break;
			default:
				ctx.transform(1, 0, 0, 1, 0, 0);
		}
		ctx.drawImage(img, 0, 0, width, height);

		var dataurl = canvas.toDataURL("image/jpeg", 1);
		/*
		canvas.toBlob(function (blob) {
			$('#reFileSize').text(Math.round(blob.size / 1024));
		}, 'image/jpeg', 1);
		*/
		B64.val(dataurl);
		$("#" + imageHolderId).empty();

		$("<img />", {
			"width": Width,
			"src": dataurl
		}).appendTo($("#" + imageHolderId));
		//alert('fin')
	});
}


補充一下如何送出submit然後上傳縮圖之後的照片到db:
利用ajax將base64字串格式的圖片上傳到Db

//更新圖檔
//imgId:base64圖片字串物件的id, hidAdNameId: 檔案名稱隱藏欄位的id, labelfileNameId:檔案名稱的label的id
function doUpdate(imgId, hidAdNameId, labelfileNameId, formId) {
	//alert(111);
	$("#" + imgId).val($("#" + imgId).val().split(",")[1]);
	//alert($("#" + labelfileNameId).text());
	//alert(222);
	$("#" + hidAdNameId).val($("#" + labelfileNameId).text());

	if ($("#" + imgId).val() == '' || $("#" + hidAdNameId).val() == '') {
		swal("請上傳圖片!", "", "error");
	}
	var postUrl = '';
	postUrl = "/AdUpdate/Edit";
	$.ajax({
		type: 'Post',
		url: postUrl,
		data: $("#" + formId).serialize(),
		success: function (data) {
			if (data.success) {
				swal({
					title: '更新成功!',
					text: '',
					type: 'success'
				}, function () {
					location.reload();
				});
			} else {
				$(".validation-summary-valid ul").empty();
				for (var i = 0; i < data.errors.length; i++) {
					var error = data.errors[i];
					$(".validation-summary-valid ul").append($("<li>").text(error));
				}
			}
		}
	});
}



參考資料:
經驗