閽堝鐩墠娴佽鐨勭函鍓嶇鍘嬬缉鍥剧墖瑙e喅鏂规澶у鏀瑰彉浜嗗浘鐗囧昂瀵告垨鑰呭帇缂╁悗鐨勫浘鐗囦綋绉棤娉曞噯纭揪鍒版湡鏈涘€艰寖鍥村唴鐨勯棶棰橈紝閫氳繃杩愮敤浜屽垎鏌ユ壘娉曞鎵炬渶浼樺帇缂╃偣鐨勬潵瀹炵幇鏃笉鏀瑰彉鍥剧墖浣撶Н锛屽張鑳芥帶鍒跺帇缂╁悗鍥剧墖浣撶Н绮惧害鐨勬晥鏋溿€傚湪鍚岀被鍨嬬殑绾墠绔帇缂╄В鍐虫柟妗堜腑瀵规瘮锛屾湰鏂囨彁鍑虹殑鏂规娌℃湁鏀瑰彉鍥剧墖浣撶Н锛屼笖鍘嬬缉鍚庣殑浣撶Н绮惧害鍙帶锛岃兘杈惧埌棰勬湡鏁堟灉銆傜爺绌剁粨鏋滆〃鏄庯紝杩欑鏂规绉戝涓旈潬璋便€傪煠擆煠擆煠?/p>
鍓嶈█
棣栧厛杩欑湡鐨勪笉鏄竴绡?code class="mq-8"> 鐐掑喎楗?/code>鐨勬枃绔狅紝灏界
鎺橀噾涓婅杩扮函鍓嶇鍘嬬缉鐨勬枃绔犲緢澶氣彫 浣嗘槸
缁嗙湅杩欎簺鏂规鐨勫帇缂╂晥鏋滈兘涓嶈兘瀹屽叏婊¤冻鎴戠殑闇€姹傦紝鍦ㄥ紶閼棴鑰佸笀杩欑瘒鏂囩珷涓彁鍑虹殑鍘嬬缉鏂规鏍稿績鍘熺悊鏄繍鐢?code class="mq-11">Canvas鐨?code class="mq-12">drawImage()鏂规硶锛屽皢澶у浘鐗囩粯鍒跺湪灏廋anvas鐢诲竷涓婂疄鐜扮瓑姣斾緥鍥剧墖鍘嬬缉锛屼絾鏄繖绉嶅帇缂╂柟寮忓帇缂╁嚭鏉ョ殑鍥剧墖浣撶Н涓嶅彲鎺с€傚緢澶氫汉鍙兘浼氳鍘嬬缉鍚庡浘鐗囦綋绉笉鏄秺灏忚秺濂藉悧锛熷叾瀹炰笉鏄殑锛岃€冭檻杩欐牱涓€涓簲鐢ㄥ満鏅€傚湪璇佸埜鍩洪噾鍏徃寮€鎴枫€佽瘉浠惰瘑鍒瓑鍦烘櫙涓嬶紝瑕佹眰浼犺緭鐨勮瘉浠剁収鐗囦笉鑳借繃澶э紝澶ぇ鐨勫紛绔お澶氫簡锛屼篃涓嶈兘澶皬锛屾洿涓嶈兘鏀瑰彉鍥剧墖灏哄锛屽惁鍒欎細閫犳垚鍚庣鐨?code class="mq-13">OCR绯荤粺璇嗗埆澶辫触鐨勬鐜囧ぇ澶ф攢鍗囷紝鏃犳硶璇诲彇鍒拌瘉浠朵笂鐨勪竴浜涘叧閿俊鎭€傚洜鑰岃繖灏辫姹傚墠绔浜庡浘鐗囧帇缂╁悗鐨勪綋绉灏藉彲鑳芥帴杩戞湡鏈涘€笺€傚彟涓€绫昏В鍐虫柟妗堟槸浣跨敤Canvas.toDataURL(type锛宔ncoderOptions)鏉ュ疄鐜板帇缂╋紝鏍稿績鍘熺悊鏄缃繖涓猠ncoderOptions鐨勫€硷紝鍗冲浘鐗囪緭鍑鸿川閲忔潵瀹炵幇鍘嬬缉鏁堟灉銆傞偅涔堝浜庝竴涓粰瀹氱殑鏂囦欢澶у皬鏈熸湜鍊硷紝鎴戜滑鏄惁鑳介€氳繃璁剧疆鍥剧墖璐ㄩ噺浣垮緱杈撳嚭鏂囦欢鏈€鎺ヨ繎鏈熸湜鍊兼槸涓€涓€煎緱鎺㈢储鐨勯棶棰樸€?/p>
瀹炵幇鎬濊矾
缁撳悎涓婅堪涓ょ鏂规瀹炵幇鍘熺悊锛屼娇鐢–anvas.toBlob(callback, type, encoderOptions)鏉ュ疄鐜帮紝閲囩敤浜屽垎鏌ユ壘娉曟潵瀵绘壘鏈€浼樼殑鍘嬬缉姣斾緥锛坋ncoderOptions鐨勫€硷級銆?br>涓轰粈涔堜娇鐢ㄧ殑鏄痶oBlob()鑰屼笉鏄痶oDataURL鍛紵 杩?code class="mq-17">涓昏鏄洜涓?/code>toBlob杩欎釜鏂规硶鏄?code class="mq-18">寮傛鐨勶紝鑰宼oDataURL鏄?code class="mq-19">鍚屾鐨勶紝鍥犺€屽湪澶氳繘绋嬩腑toDataURL瀹冧細闃诲UI娓叉煋銆傚叿浣撴潵璇磘oDataURL涓昏鎵ц浠ヤ笅涓夋鎿嶄綔锛屽皢浣嶅浘浠嶨PU绉诲埌CPU锛屽湪CPU灏嗗叾杞彉涓哄浘鐗囨牸寮忓悗锛屽啀浣跨敤base64缂栫爜灏嗗叾杞彉涓篵ase64瀛楃涓层€傝€宼oBlob鏂规硶灏嗕綅鍥句粠GPU绉诲姩CPU铏界劧鏄悓姝ユ搷浣滅殑锛屼絾鏄畠灏嗘枃浠惰浆涓哄浘鐗囨牸寮忕殑杩欎釜杩囩▼鏄紓姝ョ殑锛屼笉浼氶樆濉濽I娓叉煋锛岃€屼笖瀹冧笉闇€瑕佷娇鐢╞ase64缂栫爜鏂瑰紡灏嗗叾杞负瀛楃涓诧紝杩欎篃灏辨剰鍛崇潃toBlob浜嬪崐鍔熷€嶃€?code class="mq-20">闄ゆ涔嬪锛屽悓鏍风殑鍥剧墖鏂囦欢澶勭悊缁撴灉toDataURL鐨勭粨鏋滃崰鐢ㄧ殑鍐呭瓨姣攖oBlob瑕佸ぇ锛宼oDataURL杩斿洖缁撴灉鏄疷SVString锛屽畠瀵瑰簲 unicode 鏍囬噺鍊肩殑鎵€鏈夊彲鑳藉簭鍒楃殑闆嗗悎锛屽湪JavaScript涓繑鍥炴椂锛孶SVString 鏄犲皠鍒?String銆傚畠鐨勪綋绉瘮鍘熶簩杩涘埗鏂囦欢瑕侀珮37%宸﹀彸锛屽苟涓旀瘡娆℃偍鍦ㄦ煇涓湴鏂逛娇鐢ㄦ瀛楃涓叉椂锛屼緥濡備綔涓篋OM鍏冪礌鐨剆rc *锛屾垨鑰呴€氳繃缃戠粶璇锋眰鍙戦€佽瀛楃涓叉椂锛岃瀛楃涓查兘灏嗕細閲嶆柊寰楀埌鍒嗛厤鍒板唴瀛樸€傚洜姝わ紝浣犲嚑涔?code class="mq-21">姘歌繙閮戒笉闇€瑕佷娇鐢╰oDataURL,鍥犱负toDataURL鑳藉仛鐨勶紝toBlob鑳藉仛鐨勬洿濂姐€?br>
涓嬮潰鏉ョ粏鍒嗗疄鐜版楠わ紝鍏蜂綋濡備笅锛?br>tsx浠g爜
<input type={"file"} ref={frontRef} accept={"image/*"} onChange={uploadFile} multiple={true}/>
1. 鑾峰彇涓婁紶鏂囦欢
const uploadFile = (files: any) => {
const file = frontRef.current.files[0];
let src = getObjectUrl(file);
setCardFront(src);
const fileType = file.type.split('/')[1];
if (fileType !== 'png' && fileType !== 'jpg' && fileType !== 'jpeg') {
Toast.info('璇蜂笂浼爌ng,jpg,jpeg鏍煎紡鐨勫浘鐗?');
return;
}
};
2. 鐢熸垚棰勮鍦板潃
鐢╢ileReader鍜孶RL.createObjectURL閮藉彲浠ワ紝浣嗘槸鍚庤€呭吋瀹规€у拰鎬ц兘鏇村ソ涓€浜涖€傚綋鐒讹紝濡傛灉涓嶉渶瑕佸吋瀹逛竴浜涜€佺殑鏈哄瀷锛岀洿鎺ユ嬁鍥剧墖鏂囦欢鐢熸垚鐨刡ase64鍋氶瑙堝浘涔熷彲浠ャ€?/p>
const getObjectUrl = (file: any) => {
let url = null ;
if (window.createObjectURL!=undefined) { // basic
url = window.createObjectURL(file) ;
} else if (window.URL!=undefined) { // mozilla(firefox)
url = window.URL.createObjectURL(file) ;
} else if (window.webkitURL!=undefined) { // webkit or chrome
url = window.webkitURL.createObjectURL(file) ;
}
return url ;
};
3. file鏂囦欢鍒癷mg
const fileToImage = blob => new Promise( resolve => {
const img = new Image();
img.onload = () => resolve(img);
img.src = getObjectUrl(blob);
});
4. 灏唅mg杞崲涓篶anvas
const imgToCanvas = (img) => new Promise(resolve => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const imgWidth = img.width;
const imgHeight = img.height;
canvas.width = imgWidth;
canvas.height = imgHeight;
// 灏哄涓庡師鍥句繚鎸佷竴鑷达紝鍥犳绛夐珮绛夊
context.clearRect(0, 0, imgWidth, imgHeight);
context.drawImage(img, 0, 0, imgWidth, imgHeight);
resolve(canvas);
});
5. 寮€濮嬪帇缂?/h2>
const compress = (originfile, limitedSize) =>
new Promise(async (resolve, reject) => {
const originSize = originfile.size / 1024; // 璁$畻鏂囦欢澶у皬 鍗曚綅涓簁b
// 鑻ュ皬浜巐imitedSize锛屽垯涓嶉渶瑕佸帇缂╋紝鐩存帴杩斿洖
if (originSize < limitedSize) {
resolve({ file: originfile, msg: '浣撶Н灏忎簬鏈熸湜鍊硷紝鏃犻渶鍘嬬缉锛?});
return;
}
// 灏嗚幏鍙栧埌鐨勬枃浠舵仮澶嶆垚鍥剧墖
const img = await blobToImage(originfile);
// 浣跨敤姝ゅ浘鐗囩敓鎴愰渶瑕佺殑canvas
const canvas = await imgToCanvas(img);
// 涓鸿閬縥s绮惧害闂锛屽皢encoderOptions涔?00涓烘暣鏁帮紝鍒濆鏈€澶ize涓篗AX_SAFE_INTEGER
const maxQualitySize = { encoderOptions: 100, size: Number.MAX_SAFE_INTEGER };
// 鍒濆鏈€灏弒ize涓?
const minQualitySize = { encoderOptions: 0, size: 0 };
let encoderOptions = 100; // 鍒濆璐ㄩ噺鍙傛暟
let count = 0; // 鍘嬬缉娆℃暟
let errorMsg = ''; // 鍑洪敊淇℃伅
let compressBlob = null; // 鍘嬬缉鍚庣殑鏂囦欢Blob
// 鍘嬬缉鎬濊矾锛岀敤浜屽垎娉曟壘鏈€浣崇殑鍘嬬缉鐐?鏈€澶氬皾璇?娆″嵆鍙鐩栧叏閮ㄥ彲鑳?br> while (count < 8) {
compressBlob = await canvastoFile(canvas, 'image/jpeg', encoderOptions / 100);
const compressSize = compressBlob.size / 1024;
count++;
if (compressSize === limitedSize) { // 鍘嬬缉鍚庣殑浣撶Н涓庢湡鏈涘€肩浉绛? 鍘嬬缉瀹屾垚锛屾€诲叡鍘嬬缉浜哻ount娆?br> break;
} else if (compressSize > limitedSize) { // 鍘嬬缉鍚庣殑浣撶Н姣旀湡鏈涘€煎ぇ
maxQualitySize.encoderOptions = encoderOptions;
maxQualitySize.size = compressSize;
} else { // 鍘嬬缉鍚庣殑浣撶Н姣旀湡鏈涘€煎皬
minQualitySize.encoderOptions = encoderOptions;
minQualitySize.size = compressSize;
}
encoderOptions = (maxQualitySize.encoderOptions + minQualitySize.encoderOptions) >> 1;
if (maxQualitySize.encoderOptions - minQualitySize.encoderOptions < 2) {
if (!minQualitySize.size && encoderOptions) {
encoderOptions = minQualitySize.encoderOptions;
} else if (!minQualitySize.size && !encoderOptions) {
errorMsg = '鍘嬬缉澶辫触锛屾棤娉曞帇缂╁埌鎸囧畾澶у皬';
break;
} else if (minQualitySize.size > limitedSize) {
errorMsg = '鍘嬬缉澶辫触锛屾棤娉曞帇缂╁埌鎸囧畾澶у皬';
break;
} else { // 鍘嬬缉瀹屾垚
encoderOptions = minQualitySize.encoderOptions;
compressBlob = await canvastoFile(canvas, 'image/jpeg', encoderOptions / 100);
break;
}
}
}
// 鍘嬬缉澶辫触锛屽垯杩斿洖鍘熷鍥剧墖鐨勪俊鎭?br> if (errorMsg) {
reject({
msg: errorMsg,
file: originfile,
});
return;
}
const compressSize = compressBlob.size / 1024;
console.log(`鏈€鍚庝竴娆″帇缂╁悗锛宔ncoderOptions涓?${encoderOptions}锛屽ぇ灏忥細${compressSize}`);
// 鐢熸垚鏂囦欢
const compressedFile = new File([compressBlob], originfile.name, {
type: 'image/jpeg',
});
resolve({ file: compressedFile, compressBlob, msg: '鍘嬬缉鎴愬姛锛?});
});
const compress = (originfile, limitedSize) =>
new Promise(async (resolve, reject) => {
const originSize = originfile.size / 1024; // 璁$畻鏂囦欢澶у皬 鍗曚綅涓簁b
// 鑻ュ皬浜巐imitedSize锛屽垯涓嶉渶瑕佸帇缂╋紝鐩存帴杩斿洖
if (originSize < limitedSize) {
resolve({ file: originfile, msg: '浣撶Н灏忎簬鏈熸湜鍊硷紝鏃犻渶鍘嬬缉锛?});
return;
}
// 灏嗚幏鍙栧埌鐨勬枃浠舵仮澶嶆垚鍥剧墖
const img = await blobToImage(originfile);
// 浣跨敤姝ゅ浘鐗囩敓鎴愰渶瑕佺殑canvas
const canvas = await imgToCanvas(img);
// 涓鸿閬縥s绮惧害闂锛屽皢encoderOptions涔?00涓烘暣鏁帮紝鍒濆鏈€澶ize涓篗AX_SAFE_INTEGER
const maxQualitySize = { encoderOptions: 100, size: Number.MAX_SAFE_INTEGER };
// 鍒濆鏈€灏弒ize涓?
const minQualitySize = { encoderOptions: 0, size: 0 };
let encoderOptions = 100; // 鍒濆璐ㄩ噺鍙傛暟
let count = 0; // 鍘嬬缉娆℃暟
let errorMsg = ''; // 鍑洪敊淇℃伅
let compressBlob = null; // 鍘嬬缉鍚庣殑鏂囦欢Blob
// 鍘嬬缉鎬濊矾锛岀敤浜屽垎娉曟壘鏈€浣崇殑鍘嬬缉鐐?鏈€澶氬皾璇?娆″嵆鍙鐩栧叏閮ㄥ彲鑳?br> while (count < 8) {
compressBlob = await canvastoFile(canvas, 'image/jpeg', encoderOptions / 100);
const compressSize = compressBlob.size / 1024;
count++;
if (compressSize === limitedSize) { // 鍘嬬缉鍚庣殑浣撶Н涓庢湡鏈涘€肩浉绛? 鍘嬬缉瀹屾垚锛屾€诲叡鍘嬬缉浜哻ount娆?br> break;
} else if (compressSize > limitedSize) { // 鍘嬬缉鍚庣殑浣撶Н姣旀湡鏈涘€煎ぇ
maxQualitySize.encoderOptions = encoderOptions;
maxQualitySize.size = compressSize;
} else { // 鍘嬬缉鍚庣殑浣撶Н姣旀湡鏈涘€煎皬
minQualitySize.encoderOptions = encoderOptions;
minQualitySize.size = compressSize;
}
encoderOptions = (maxQualitySize.encoderOptions + minQualitySize.encoderOptions) >> 1;
if (maxQualitySize.encoderOptions - minQualitySize.encoderOptions < 2) {
if (!minQualitySize.size && encoderOptions) {
encoderOptions = minQualitySize.encoderOptions;
} else if (!minQualitySize.size && !encoderOptions) {
errorMsg = '鍘嬬缉澶辫触锛屾棤娉曞帇缂╁埌鎸囧畾澶у皬';
break;
} else if (minQualitySize.size > limitedSize) {
errorMsg = '鍘嬬缉澶辫触锛屾棤娉曞帇缂╁埌鎸囧畾澶у皬';
break;
} else { // 鍘嬬缉瀹屾垚
encoderOptions = minQualitySize.encoderOptions;
compressBlob = await canvastoFile(canvas, 'image/jpeg', encoderOptions / 100);
break;
}
}
}
// 鍘嬬缉澶辫触锛屽垯杩斿洖鍘熷鍥剧墖鐨勪俊鎭?br> if (errorMsg) {
reject({
msg: errorMsg,
file: originfile,
});
return;
}
const compressSize = compressBlob.size / 1024;
console.log(`鏈€鍚庝竴娆″帇缂╁悗锛宔ncoderOptions涓?${encoderOptions}锛屽ぇ灏忥細${compressSize}`);
// 鐢熸垚鏂囦欢
const compressedFile = new File([compressBlob], originfile.name, {
type: 'image/jpeg',
});
resolve({ file: compressedFile, compressBlob, msg: '鍘嬬缉鎴愬姛锛?});
});
涓轰粈涔堟渶澶氬皾璇曞叓娆″嵆鍙鐩栧叏閮ㄥ彲鑳藉憿锛?/span> 杩欐槸鍥犱负2^7 = 128锛?鑰?/128=0.0078125锛岃€宔ncoderOptions鐨勬渶灏忛绮掑害涓?.01锛屽洜姝ゅ啀鍘嬬缉涓嬪幓宸茬粡娌℃湁鎰忎箟浜嗐€?br> 鍚庣涓庢垜绾﹀畾鏈€澶т綋绉负300kb锛屾嬁鍒板帇缂╃粨鏋渞es鍚庡氨鍙互鎰夊揩鐨勫彂缁欎粬浠簡銆傪煠楌煠楌煠?/p>
寰堝鏃跺€欙紝鎴戜滑闄や簡鍏虫敞鍘嬬缉鍚庡浘鐗囩殑浣撶Н涔嬪锛岃繕鏈熸湜浠庢劅瀹樹笂鐩磋鍦版潵浣撻獙涓€涓嬪帇缂╁悗鐨勫浘鐗囨竻鏅板害濡備綍锛岄偅涔堝彲浠ヨ繖鏍锋潵涓嬭浇鍘嬬缉浠ュ悗鐨勫浘鐗囪繘琛岃瀵熴€?/p>
鍐欒繖绡囨枃绔犵殑鏃跺€欙紝杩樿皟鐮斾簡寰堝缃戜笂浣跨敤鐜囪緝楂樼殑鍘嬬缉缁勪欢锛屾瘮杈冩祦琛屼娇鐢ㄧ殑鏈塴rz,瀹冪殑浣跨敤璇硶濡備笅锛?br>(file, [options]);娉ㄦ剰锛?/code> canvas.toBlob鍦∕DN鏂囨。涓婃槑纭鏄庯紝鍙€夊弬鏁癳ncoderOptions鏄疦umber绫诲瀷锛屽€煎湪0涓?涔嬮棿锛屽綋璇锋眰鍥剧墖鏍煎紡涓篿mage/jpeg鎴栬€卛mage/webp鏃剁敤鏉ユ寚瀹氬浘鐗囧睍绀鸿川閲忋€備篃灏辨槸璇村帇缂╃殑鏃跺€欏彧鏀寔jpeg/webp杩欎袱绉嶆牸寮忥紝鍥犳锛岄渶瑕佸皢type璁惧畾涓?code class="mq-50">image/jpeg
銆?/p>
6. 鍘嬬缉瀹屾垚
compress(file, 300).then((res: any) => {
Toast.success(res.msg);
console.log(res);
}, (err: any) => {
Toast.fail(err.msg);
});7. 琛ュ厖
const downLoadImg = (blob) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = 'fileName'; // 鏂囦欢鍛藉悕
link.click();
link.remove();
URL.revokeObjectURL(link.href);
};鎬荤粨
1銆乫ile 閫氳繃 input:file 寰楀埌鐨勬枃浠讹紝鎴栬€呯洿鎺ヤ紶鍏ュ浘鐗囪矾寰?br>2銆乕options] 杩欎釜鍙傛暟鍏佽蹇界暐
3銆亀idth {Number} 鍥剧墖鏈€澶т笉瓒呰繃鐨勫搴︼紝榛樿涓哄師鍥惧搴︼紝楂樺害涓嶈鏃朵細閫傚簲瀹藉害銆?br>4銆乭eight {Number} 鍚屼笂
5銆乹uality {Number} 鍥剧墖鍘嬬缉璐ㄩ噺锛屽彇鍊?0 - 1锛岄粯璁や负0.7
6銆乫ieldName {String} 鍚庣鎺ユ敹鐨勫瓧娈靛悕锛岄粯璁わ細file
鏃犳硶灏嗗浘鐗囧帇缂╁埌鎸囧畾浣撶Н闄勮繎锛屼緷鏃ч渶瑕佷綘鍘绘帰绱uality鐨勫彇鍊笺€傝繕鏈変竴涓彃浠舵槸image-conversion锛屽畠鏈変竴涓猘pi鍙玞ompressAccurately(file, config) 鈫?{Promise(Blob)}锛岃缃蹇嶈宸害鍚庯紝鑳藉灏嗗浘鐗囦綋绉帇缂╁埌鎸囧畾鍊肩殑闄勮繎锛屼絾鏄繕闆嗘垚浜嗗緢澶氬叾浠栦笉闇€瑕佺殑鍔熻兘锛屽洜姝や笉濡傝嚜宸卞姩鎵嬩赴琛h冻椋燂紝椤轰究娣卞叆瀛︿範瀛︿範锛屾帰绌跺叾鍘熺悊锛屽矀涓嶇編鍝夝煒?br>