多画像圧縮アップロードとiOS端末画像アップロードの選択90度の問題を解決します.

28703 ワード

論理的思考:1、inputファイル値のchangeイベント2、ファイルリストを取得する3、FileReader関数を使って画像情報を読み取り、base 64フォーマットに変更する4、予め設定したしきい値に基づいて5を圧縮するかどうかを判断し、圧縮しない場合はFormData関数を使って画像をアップロードします.必要に応じて、瓦canvas 7を使って、Exif.jsを使って、写真の方向情報を取得するかどうかを選択し、canvasのrotate()関数を使って回転画像8、アップロードピクチャを行う必要があるかを判断する.
カスタム画像アップロードコンポーネント:
//  

//           ,    Chrome    ,                

exif.jsを導入する
import Exif from 'exif-js'
具体的に実現する
upload(e) {
				let files = e.target.files || e.dataTransfer.files;
				if (!files.length) return;
				this.picValue = files[0];
				this.imgPreview(this.picValue);
			},

			//    、  、  
			imgPreview(file) {
				let self = this;
				let Orientation;
				//         ,            
				Exif.getData(file, function() {
					Orientation = Exif.getTag(this, 'Orientation');
				});
				// alert(Orientation,'console.log(Orientation)');
				debugger
				//       FileReader
				if (!file || !window.FileReader) return;

				// alert(file);
				//     reader
				let reader = new FileReader();
				//    2    base64   
				reader.readAsDataURL(file);
				//         
				reader.onloadend = function() {

					let result = this.result;
					let img = new Image();

					img.onload = function() {
						let data = self.compress(img, Orientation);
						/*self.headerImage = data;  */
						var blob = self.dataURItoBlob(data);
						var fd = new FormData();
						fd.append("file", blob, 'image.png');
						fd.fileName = blob;
						console.log(fd, 'fd')
						axios.post('/sunrise-gateway/oss/ossUpload', fd).then((res) => {
							return res
						}).then((res) => {
							console.log(res, 'res')
							if (res.data.code == '000000') {
								self.list.push(...res.data.data);
								self.objUrl = res.data.data[0];
								self.picNum++;
							} else {
								MessageBox.alert('    0');
							}
							Indicator.close();
						}).catch((err) => {
							Indicator.close();
							MessageBox.alert('    1');
						})
						// alert(blob)
					}
					img.src = result;
				}
			},

			//base64 blob
			dataURItoBlob(base64Data) {
				var byteString;
				if (base64Data.split(',')[0].indexOf('base64') >= 0) {
					byteString = atob(base64Data.split(',')[1]);
				} else {
					byteString = unescape(base64Data.split(',')[1]);
				}
				var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
				var ia = new Uint8Array(byteString.length);
				for (var i = 0; i < byteString.length; i++) {
					ia[i] = byteString.charCodeAt(i);
				}
				return new Blob([ia], {
					type: mimeString
				});
			},

			//    
			rotateImg(img, direction, canvas) {
				//         ,    4       
				const min_step = 0;
				const max_step = 3;
				if (img == null) return;
				//img         img       ,     
				let height = img.height;
				let width = img.width;
				let step = 2;
				if (step == null) {
					step = min_step;
				}
				if (direction == 'right') {
					step++;
					//      ,      
					step > max_step && (step = min_step);
				} else {
					step--;
					step < min_step && (step = max_step);
				}
				//           
				let degree = step * 90 * Math.PI / 180;
				let ctx = canvas.getContext('2d');
				switch (step) {
					case 0:
						canvas.width = width;
						canvas.height = height;
						ctx.drawImage(img, 0, 0);
						break;
					case 1:
						canvas.width = height;
						canvas.height = width;
						ctx.rotate(degree);
						ctx.drawImage(img, 0, -height);
						break;
					case 2:
						canvas.width = width;
						canvas.height = height;
						ctx.rotate(degree);
						ctx.drawImage(img, -width, -height);
						break;
					case 3:
						canvas.width = height;
						canvas.height = width;
						ctx.rotate(degree);
						ctx.drawImage(img, -width, 0);
						break;
				}
			},

			//    
			compress(img, Orientation) {
			let canvas = document.createElement('canvas');
					let ctx = canvas.getContext('2d');
					//  canvas
					let tCanvas = document.createElement('canvas');
					let tctx = tCanvas.getContext('2d');
					let initSize = img.src.length;
					let width = img.width;
					let height = img.height;
					//           ,           400   
					let ratio;
					if ((ratio = width * height / 4000000) > 1) {
						// console.log('  400   ')
						ratio = Math.sqrt(ratio);
						width /= ratio;
						height /= ratio;
					} else {
						ratio = 1;
					}
					canvas.width = width;
					canvas.height = height;
					//   
					ctx.fillStyle = '#fff';
					ctx.fillRect(0, 0, canvas.width, canvas.height);
					//        100        
					let count;
					if ((count = width * height / 1000000) > 1) {
						// console.log('  100W  ');
						count = ~~(Math.sqrt(count) + 1); //          
						//          
						let nw = ~~(width / count);
						let nh = ~~(height / count);
						tCanvas.width = nw;
						tCanvas.height = nh;
						for (let i = 0; i < count; i++) {
							for (let j = 0; j < count; j++) {
								tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
								ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
							}
						}
					} else {
						ctx.drawImage(img, 0, 0, width, height);
					}
					//  ios              
					if (Orientation != '' && Orientation != 1) {
						switch (Orientation) {
							case 6: //     (  )90   
								this.rotateImg(img, 'left', canvas);
								break;
							case 8: //     (  )90   
								this.rotateImg(img, 'right', canvas);
								break;
							case 3: //  180   
								this.rotateImg(img, 'right', canvas); //   
								this.rotateImg(img, 'right', canvas);
								break;
						}
					}
					//      	
					let ndata = canvas.toDataURL('image/jpeg', 0.1);
					tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
					return ndata;
				},
備考:canvas.toData URL()方法は、画像展示を含むdata URIを返す.typeパラメータはそのタイプが使用できます.デフォルトはイメージ/png形式です.画像の解像度は96 dpiです.
イメージフォーマットがイメージ/jpegまたはイメージ/webpである場合は、0から1までの区間でピクチャの品質を選択することができます.取得範囲を超えた場合、標準値0.92が使用されます.他のパラメータは無視されます.
戻り値:dataURIを含むDOMString.
DataURIフォーマット:data:[;;base 64]この中でmediatypeはファイルタイプを宣言しました.MIMEルールに従います.例えば、「image/png」、「text/playin」.その後はコードタイプです.ここではbase 64だけを扱っています.続いてファイルコードの内容です.
URI(Uniflom Resource Identifer):統一リソース識別子、サーバリソース名は統一リソース識別子と呼ばれています.
URL(Uniflom Resource Locator):統一リソースロケータは、特定のサーバ上のリソースの特定の位置を記述しています.例えば:
img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAWCAYAAAArdgcFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABSUlEQVQ4Ee1VPUsDQRB9s3dBRCRNQvCjkDQW/hJ/gb9AOwWDoIXFgYXYXGP+hYW1/gIr7WzsE8VGxZBcwt04dznCJWw2twtWutXMmzdvlrd7t4SZVbvi1ZihZuCFqT9A/B7Qd5FI44RpPcQpE1oC1IsEq5jRBeGyc0zXaV8mvhbyOREurIRMZMZhp0VthYB9mXBi4jrUztIev1bNbKg6CMxvIWwg5GWVDOHNZ7lX6l/wrG+Fzbh/ca1bf9QWBhKtHznobgtjKF92ZBL3TUWpRbK7LhiVCY8kY3xK/iTiexNcEywSXxKBrfHvrdBN2JRsp4BoQ3dbtHLT4K+JqxWw8vr4YDaf+vR+SmXRWw99lT9N96VaypIYtwgoyWyJRtiX3T+X7TXxROcxGeAo5chlyNcBVxrb2JVpTUHsz4IQi/DL6wPucENxqvoDx69PXP8OKn4AAAAASUVORK5CYII='/