ปัญหานี้เกิดจากการที่เมื่ออัปโหลดไฟล์ภาพ พื้นหลังจะจำกัดขนาดไว้ที่ 2MB แต่เมื่อเปิดกล้องเพื่อถ่ายภาพ จะเกิน 2MB ทุกๆ นาที เพื่อไม่ให้ส่งผลกระทบต่อประสบการณ์ผู้ใช้และข้อกำหนดด้านการทำงาน ส่วนหน้าจะต้องบีบอัดขนาดแล้วอัปโหลดไปที่หลังเวที
การวิเคราะห์ความคิดหลังจากค้นหาข้อมูลมากมาย ฉันพบว่ามีเพียง Canvas เท่านั้นที่สามารถบีบอัดรูปภาพได้
หลักการคร่าวๆ มีดังนี้ 1. ขั้นแรกให้แปลงไฟล์รูปภาพเป็น baseURL 2. สร้างแท็กรูปภาพเพื่อรับไฟล์และรับความกว้าง ความสูง และสัดส่วนของรูปภาพ 3. สร้างผืนผ้าใบและกำหนดขนาดของผืนผ้าใบ 4. วาดภาพลงบนผืนผ้าใบ 5. บีบอัดแคนวาสและรับ baseURL ใหม่ 6. แปลง baseURL กลับเป็นไฟล์
หน้าที่ของสถานที่ตั้ง แปลงไฟล์ไฟล์เป็น base64 /*** @param {binary file stream} file * @param {callback function, return base64} fn */function changeFileToBaseURL(file,fn){ // สร้างอ็อบเจ็กต์ไฟล์อ่าน var fileReader = new FileReader(); หากไม่ได้กำหนดไฟล์ ให้คืนค่า null ถ้า (ไฟล์ == ไม่ได้กำหนด) ให้คืนค่า fn(null); // อ่านไฟล์ ไฟล์ผลลัพธ์คือ base64-bit fileReader.readAsDataURL(file); fileReader.onload = function(){ // อ่าน base64 var imgBase64Data = this.result; fn(imgBase64Data); แปลง base64 เป็นสตรีมไฟล์ /** * แปลง base64 เป็นไฟล์ * @param {baseURL} dataurl * @param {ชื่อไฟล์} ชื่อไฟล์ * @return {file binary stream}*/function dataURLtoFile(dataurl, filename) { var arr = dataurl.split(' , '), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = ใหม่ Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } ส่งคืนไฟล์ใหม่ ([u8arr], ชื่อไฟล์, {type: mime}); วิธีการบีบอัด /*** ภาพบีบอัดแคนวาส* @param {parameter obj} param * @param {file binary stream} param.file required* @param {ขนาดการบีบอัดเป้าหมาย} param.targetSize ไม่ผ่านการกำหนดเริ่มต้น -1* @param {output Image width} param.width ไม่ผ่านค่าการกำหนดเริ่มต้น -1 และไม่ผ่านความสูงสำหรับการปรับขนาดตามสัดส่วน* @param {ชื่อรูปภาพเอาต์พุต} param.fileName ไม่ผ่านรูปภาพการกำหนดเริ่มต้น* @param {องศาภาพที่บีบอัด } param.quality ไม่ผ่านค่ากำหนดเริ่มต้นที่ 0.92 ช่วงค่า 0~1* @param {ฟังก์ชันการเรียกกลับ} จำเป็นต้องใช้ param.succ */ฟังก์ชัน pressImg(param){/ //หากไม่มีฟังก์ชันการเรียกกลับ มันจะไม่ถูกดำเนินการถ้า(param && param.succ){ //ถ้า ไม่ได้กำหนดไฟล์ ให้คืนค่า null if(param.file == unknown) return param.succ(null); //แนบค่าเริ่มต้นให้กับพารามิเตอร์ param.targetSize = param.hasOwnProperty(targetSize)? param.targetSize : -1; param.width = param.hasOwnProperty(width) ? param.width : -1; param.fileName = param.hasOwnProperty(ชื่อไฟล์) ? คุณภาพ) ? param.quality : 0.92; var _this = this; // รับประเภทไฟล์ var fileType = param.file.type; // console.log(fileType) //image/jpeg if(fileType.indexOf(image) == -1){ console.log('กรุณาเลือกไฟล์รูปภาพ^_^'); return param.succ(null); } //หากขนาดปัจจุบันเล็กกว่าขนาดเป้าหมาย ให้ส่งออก var size = param.file.size; if(param.targetSize > size){ return param.succ(param.file ) } / / อ่านไฟล์ไฟล์และผลลัพธ์คือ base64 changeFileToBaseURL(param.file,function(base64){ if(base64){ var image = new Image(); image.src = base64; image.onload = function(){ / / Get อัตราส่วนภาพ var scale = this.width / this.height; // console.log(scale); //สร้าง canvas var canvas = document.createElement('canvas'); // รับบริบท var context = canvas.getContext('2d'); // รับความกว้างของภาพที่บีบอัด หากความกว้างเป็น -1 ความกว้างของภาพต้นฉบับเริ่มต้น canvas.width = param.width == -1? width : param.width; // รับความสูงของรูปภาพที่ถูกบีบอัด หากความกว้างเป็น -1 ความสูงของรูปภาพดั้งเดิมคือ canvas.height = param.width == -1? parseInt(param.width / scale); //วาดภาพลงบนผืนผ้าใบ context.drawImage(image, 0, 0, canvas.width, canvas.height); // บีบอัดรูปภาพและรับ base64Url ใหม่ var newImageData = canvas toDataURL(fileType,param.quality); //แปลง base64 เป็นสตรีมไฟล์ var resultFile = dataURLtoFile(newImageData,param.fileName); //ตัดสินว่า targetSize ถูกจำกัดและขนาดภาพที่บีบอัดมีขนาดใหญ่กว่าขนาดเป้าหมาย ข้อผิดพลาดจะปรากฏขึ้นถ้า(param.targetSize != -1 && param.targetSize < resultFile.size ){ console .log(ขนาดการอัพโหลดรูปภาพใหญ่เกินไป โปรดอัปโหลดใหม่^_^); param.succ(null) //ส่งคืนไฟล์กระแส param.succ(resultFile); การใช้วิธีการขนาดของไฟล์เป็นไบต์ ดังนั้นเราจึงต้องแปลงขนาดที่ต้องการเป็นไบต์ 1 ไบต์คือ 1 ไบต์คือ 1B, 1KB = 1024B, 1MB = 1024 * 1024B
<ชนิดอินพุต=ไฟล์ id=คลาส fileImg=fileImg/>
//รับไฟล์รูปภาพที่อัพโหลด url$(#fileImg).on('change',function(){ pressImg({ file:this.files[0], targetSize:2 * 1024 * 1024, quality:0.5, width:600 , succ:function(resultFile){ //ถ้าไม่เป็น null แสดงว่าการบีบอัดข้อมูลสำเร็จ if(resultFile){ //TODO } } })}); สรุปปัญหา ระดับการบีบอัดภาพระดับการบีบอัดของภาพนั้นไม่ใช่เรื่องง่ายที่จะกำหนด ดังนั้นคุณสามารถลองได้หลายครั้งและปรับแต่งตามความต้องการของผู้เรียกร้อง การเปลี่ยนขนาดและความละเอียดของภาพเป้าหมายสามารถเปลี่ยนระดับการบีบอัดภาพได้
เดิมทีฉันต้องการทำกระบวนการบีบอัดรูปภาพแบบเรียกซ้ำจนกว่าขนาดรูปภาพจะตรงตามความคาดหวังภายหลังได้ทราบ
เพราะเมื่อ iOS เรียกกล้องของระบบมาถ่ายรูป กล้องจะหมุน 90 องศาทวนเข็มนาฬิกา หลังจากที่ฉันบีบอัดภาพและส่งไปที่พื้นหลัง ฉันพบว่าทิศทางการถ่ายภาพของข้อมูล exif ของภาพหายไป ทำให้ภาพที่อัปโหลดโดย iOS หมุน 90 องศาทวนเข็มนาฬิกา Android ไม่เคยสังเกตเห็นปัญหานี้เลย
ปัจจุบันมีข้อสงสัยว่าไฟล์ดังกล่าวจะหายไปเมื่อแปลง base64 เป็นไฟล์ไฟล์ คำแนะนำเพิ่มเติมจะระบุไว้ที่นี่หลังการตรวจสอบ
@ version1.0-2019-8-2-Create "ใช้ canvas เพื่อบีบอัดขนาดภาพ"
©burning_Yun Qiqi
ข้างต้นคือเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาของทุกคน ฉันหวังว่าทุกคนจะสนับสนุน VeVb Wulin Network