Masalah ini bermula dari fakta bahwa saat mengunggah file gambar, latar belakang membatasi ukurannya hingga 2MB, namun saat kamera dihidupkan untuk mengambil gambar, ukurannya melebihi 2MB setiap menitnya. Agar tidak mempengaruhi pengalaman pengguna dan persyaratan fungsional, itu front-end perlu mengompresi ukurannya dan kemudian mengunggahnya.
Analisis ideSetelah mencari banyak informasi, saya menemukan bahwa hanya kanvas yang dapat mengompresi gambar.
Prinsipnya kira-kira sebagai berikut: 1. Pertama-tama ubah file file gambar menjadi baseURL 2. Buat tag gambar untuk menerima file dan dapatkan lebar, tinggi dan proporsi gambar. 3. Buat kanvas dan atur ukuran kanvas. 4. Gambarlah gambar tersebut pada kanvas. 5. Kompres kanvas dan dapatkan baseURL baru 6. Konversi baseURL kembali menjadi file.
fungsi premis Konversi file file ke base64 /*** @param {binary file stream} file * @param {callback function, return base64} fn */function changeFileToBaseURL(file,fn){ // Membuat objek file baca var fileReader = new FileReader(); Jika file tidak terdefinisi, return null if(file == undefinisi) return fn(null); // Baca file file, hasilnya adalah fileReader.readAsDataURL(file); fileReader.onload = function(){ // Membaca base64 var imgBase64Data = this.result; Konversikan base64 ke aliran file /** * Konversi base64 ke file * @param {baseURL} dataurl * @param {nama file} nama file * @return {file biner stream}*/function dataURLtoFile(dataurl, nama file) { var arr = dataurl.split(' , '), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } kembalikan File baru([u8arr], nama file, {type:mime} } Metode kompresi /*** gambar terkompresi kanvas* @param {parameter obj} param * @param {file biner stream} param.file diperlukan* @param {ukuran kompresi target} param.targetSize tidak lulus penugasan awal -1* @param {output Lebar gambar} param.width tidak melewati nilai tugas awal -1, dan tidak melewati tinggi untuk penskalaan proporsional* @param {nama gambar keluaran} param.fileName tidak melewati nilai tugas awal image* @param {derajat gambar terkompresi } param.quality tidak melewati nilai penugasan awal sebesar 0,92. Rentang nilai 0~1* @param {fungsi panggilan balik} param.succ diperlukan */fungsi pressImg(param){ //Jika tidak ada fungsi panggilan balik, fungsi tersebut tidak akan dieksekusi if(param && param.succ){ //Jika file tidak ditentukan, kembalikan null if(param.file == tidak terdefinisi) return param.succ(null); //Lampirkan nilai awal ke parameter param.targetSize = param.hasOwnProperty(targetSize)? param.targetUkuran : -1; param.lebar = param.hasOwnProperty(lebar) ? param.lebar : -1; param.namafile = param.hasOwnProperty(namafile) ? kualitas) ? param.kualitas : 0.92; var _this = ini; // Dapatkan jenis file var fileType = param.file.type; // console.log(fileType) //image/jpeg if(fileType.indexOf(image) == -1){ console.log('Silakan pilih file gambar^_^'); return param.succ(null); } //Jika ukuran saat ini lebih kecil dari ukuran target, langsung keluarkan var size = param.file.size if(param.targetSize > size){ return param.succ(param.file ); Baca file file dan hasilnya adalah base64 changeFileToBaseURL(param.file,function(base64){ if(base64){ var image = new Image(); image.src = base64; image.onload = function(){ / / Dapatkan rasio aspek var skala = this.width / this.height; // console.log(scale); //Membuat kanvas var canvas = document.createElement('canvas'); //Dapatkan konteks var konteks = canvas.getContext('2d'); //Dapatkan lebar gambar terkompresi. Jika lebarnya -1, lebar gambar asli default canvas.width = param.width == -1 ini. width : param.width; //Dapatkan tinggi gambar terkompresi. Jika lebarnya -1, tinggi gambar asli default adalah canvas.height = param.width == -1? parseInt(param.width / scale); //Gambarkan gambar ke dalam kanvas konteks.drawImage(gambar, 0, 0, kanvas.lebar, kanvas.tinggi); //Kompres gambar dan dapatkan base64Url baru var newImageData = kanvas .toDataURL(fileType,param.quality); //Ubah base64 menjadi aliran file var resultFile = dataURLtoFile(newImageData,param.fileName); //Menilai jika targetSize terbatas dan ukuran gambar terkompresi lebih besar dari ukuran target, kesalahan akan muncul if(param.targetSize != -1 && param.targetSize < resultFile.size ){ console .log(Ukuran unggahan gambar terlalu besar, harap unggah ulang^_^); param.succ(null); //Kembalikan aliran file param.succ(resultFile); Penggunaan metodeUkuran file dalam satuan byte, jadi kita perlu mengubah ukuran yang diperlukan menjadi byte. 1 byte adalah 1 byte adalah 1B, 1KB = 1024B, 1MB = 1024 * 1024B
<tipe masukan=id file=fileImg kelas=fileImg/>
//Dapatkan unggah file gambar url$(#fileImg).on('change',function(){ pressImg({ file:this.files[0], targetSize:2 * 1024 * 1024, kualitas:0.5, lebar:600 , succ:function(resultFile){ //Jika bukan null, kompresi berhasil if(resultFile){ //TODO } } })}); Ringkasan masalah Tingkat kompresi gambarTingkat kompresi gambar tidak mudah untuk ditentukan, sehingga Anda dapat mencobanya berkali-kali dan menyesuaikannya sesuai dengan kebutuhan peminat. Mengubah ukuran dan resolusi gambar target dapat mengubah tingkat kompresi gambar.
Awalnya saya ingin melakukan proses kompresi gambar secara rekursif hingga ukuran gambar memenuhi harapan.Belakangan ketahuan
Karena saat ios memanggil sistem kamera untuk mengambil gambar, diputar 90 derajat berlawanan arah jarum jam. Setelah saya mengompres gambar dan mengirimkannya ke latar belakang, saya menemukan bahwa arah pengambilan gambar informasi geofis gambar tersebut hilang, menyebabkan gambar yang diunggah oleh iOS diputar 90 derajat berlawanan arah jarum jam. Android tidak pernah menyadari masalah ini.
Saat ini, ada kecurigaan bahwa file tersebut hilang ketika base64 diubah menjadi file file. Petunjuk tambahan akan diberikan di sini setelah verifikasi.
@version1.0-2019-8-2-Buat "Gunakan kanvas untuk mengompresi ukuran gambar"
©membakar_Yun Qiqi
Di atas adalah keseluruhan isi artikel ini, saya harap dapat bermanfaat untuk pembelajaran semua orang. Saya juga berharap semua orang mendukung VeVb Wulin Network.