1.建立組件components > uploadImg > index.vuevue
<template> <input type="file" name="pic" ref="file" accept="image/*" @change="upload"/> </template> <script> import Exif from "exif-js"; import { upload } from "@/api"; export default { props: { }, data() { return { uploadName: "" }; }, mounted() { console.log(this.uploadType); }, methods: { upload(e) { if (e.target.files.length > 0) { this.$vux.loading.show("Loading..."); let files = e.target.files || e.dataTransfer.files; if (!files.length) return; this.picValue = files[0] this.uploadName = files[0].name; // 上傳圖片 var u = navigator.userAgent, app = navigator.appVersion; var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //g var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios終端 if (isAndroid) { this.axiosFun(this.picValue); } if (isIOS) { this.imgPreview(this.picValue); } // 上傳視頻 // this.axiosFun(this.picValue); } }, imgPreview(file) { let self = this; let Orientation; //去獲取拍照時的信息,解決拍出來的照片旋轉問題 Exif.getData(file, function() { Orientation = Exif.getTag(this, "Orientation"); }); // 看支持不支持FileReader if (!file || !window.FileReader) return; if (/^image/.test(file.type)) { // 建立一個reader let reader = new FileReader(); // 將圖片2將轉成 base64 格式 reader.readAsDataURL(file); // 讀取成功後的回調 reader.onloadend = function() { let result = this.result; let img = new Image(); img.src = result; //判斷圖片是否大於100K,是就直接上傳,反之壓縮圖片 if (this.result.length <= 100 * 1024) { self.headerImage = this.result; self.postImg(); } else { img.onload = function() { let data = self.compress(img, Orientation); self.headerImage = data; self.postImg(); }; } }; } }, compress(img, Orientation) { let _this = this 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, "right2", canvas); break; } } //進行最小壓縮 let ndata = canvas.toDataURL("image/jpeg", 0.1); tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0; return ndata; }, 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 if (direction == "right2") { step = 2; } 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; } }, postImg() { //這裏寫接口 // console.log(this.headerImage) const block = this.headerImage.split(";"); const contentType = block[0].split(":")[1]; // In this case "image/jpeg" const realData = block[1].split(",")[1]; // In this case "R0lGODlhPQBEAPeoAJosM...." var blob = this.b64toBlob(realData, contentType); this.axiosFun(blob); }, uploadDefined(file, data, callback) { let _this = this; let gObjectName = data.dir + this.randomString() + this.getSuffix(this.uploadName); let request = new FormData(); request.append("OSSAccessKeyId", data.accessid); // Bucket 擁有者的Access Key Id。 request.append("policy", data.policy); // policy規定了請求的表單域的合法性 request.append("Signature", data.signature); // 根據Access Key Secret和policy計算的簽名信息,OSS驗證該簽名信息從而驗證該Post請求的合法性 request.append("key", gObjectName); // 文件名字,可設置路徑 request.append("success_action_status", "200"); // 讓服務端返回200,否則,默認會返回204 request.append("x-oss-object-acl", "public-read"); request.append("file", file); let xhr = new XMLHttpRequest(); xhr.open("POST", data.host); xhr.send(request); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { // console.log("fileKey => " + data.host + "/" + gObjectName); // console.log(_this.imgPaths); _this.$vux.loading.hide(); callback(data.host, gObjectName); } else if (xhr.status === 400){ _this.$vux.loading.hide(); _this.$vux.toast.text('圖片太大,請換取小的圖片') } }; }, async imgUpload(){ // const { data } = await uploadImg({url: host, }) }, async axiosFun(blob) { let that = this; const { data } = await upload({}); that.uploadDefined(blob, data, function(host, name) { that.$emit("uploadImage", { value: host + "/" + name, }); }); }, randomString(len) { len = len || 32; var chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"; var maxPos = chars.length; var pwd = ""; for (var i = 0; i < len; i++) { pwd += chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; }, getSuffix(filename) { var pos = filename.lastIndexOf("."); var suffix = ""; if (pos !== -1) { suffix = filename.substring(pos); } return suffix; }, b64toBlob(b64Data, contentType = "", sliceSize = 512) { const byteCharacters = atob(b64Data); const byteArrays = []; for ( let offset = 0; offset < byteCharacters.length; offset += sliceSize ) { const slice = byteCharacters.slice(offset, offset + sliceSize); const byteNumbers = new Array(slice.length); for (let i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } const blob = new Blob(byteArrays, { type: contentType }); return blob; } } }; </script> <style> </style>
2.頁面中引用組件ios
<script> import uploadImg from '@/components/uploadImg' export default { data () { return { imgList: [], } }, components: { uploadImg }, methods: { uploadImage(val){ // 將上傳的圖片放入數組中 this.imgList.push(val.value) }, }</script>