この記事では主に H5 画像の圧縮とアップロードの例を詳しく紹介します。興味のある方は参考にしてください。
フロントエンドで画像を圧縮できるかどうかという質問がありました。一部の画像は大きすぎるため、サーバーに転送して圧縮するには遅すぎます。私は意識の中でこのようなプレイをしたことがありませんでしたが、朝上司からZhihuのリンクが送られてきました。それを見ると、先輩たちはすでにCanvasを使用してそれを実装していたことがわかりました(3秒間自分の知識を恥ずかしく思いました)。そしてすぐに働き始めました)! 。
canvas圧縮
は、githubの既製のライブラリを使用します: https://github.com/sTOMITA/ios-imagefile-megapixel 偉大な神sTOMITAを崇拝する必要があります。一般的な考え方は、画像をサンプリングしてキャンバスに表示し、canvas.toDataURL メソッドを使用して Base64 文字列を取得して圧縮を実現することです。たとえば、input 要素が変更イベントをトリガーした後、内部のファイルを読み取って操作します:
var fileInput = document.getElementById('fileInput'); fileInput.onchange = function() { var file = fileInput.files[0]; // 创建一个压缩对象,该构造函数接收file或者blob。 var mpImg = new MegaPixImage(file); // render方法的maxWith,maxHeight,以及quality都决定了压缩图片的质量 var resImg = document.getElementById('resultImage'); mpImg.render(resImg, { maxWidth: 300, maxHeight: 300, quality: 0.5 }); }; 压缩完成会得到
これに似た画像:
data:image/jpeg この形式はよく使用されており、中の背景画像はこんな感じです。
ここでの resImg はプレビュー画像であり、プレビューが必要ない場合は、圧縮用の画像 (document.createElement("img")) を作成します。これにより、tagName 属性が 1 つ少なくなります。ソース コードを変更することも、この属性を自分で追加することもできます。ソースコードはタグ名に基づいて判断され、存在しない場合はエラーが報告されます:
MegaPixImage.prototype.render = function (target, options, callback) { //.... target.tagName = target.tagName || "IMG"; //加上这一句 var tagName = target.tagName.toLowerCase(); if (tagName === 'img') { target.src = renderImageToDataURL(this.srcImage, opt, doSquash); } else if (tagName === 'canvas') { renderImageToCanvas(this.srcImage, target, opt, doSquash); } if (typeof this.onrender === 'function') { this.onrender(target); } if (callback) { callback(); } if (this.blob) { this.blob = null; URL.revokeObjectURL(this.srcImage.src); } };
また、これは時間のかかる操作です。複数の画像が圧縮されている場合は実行できません。直接呼び出すと、少し変換する必要があります。そうしないと、前のピクチャが圧縮されずに後のピクチャに入ります。
fileSelected: function () { var files = $("#fileImage")[0].files; var count = files.length; console.log("共有" + count + "个文件"); for (var i = 0; i < count; i++) {var item = files[i]; console.log("原图片大小", item.size); if (item.size > 1024 * 1024 * 2) { console.log("图片大于2M,开始进行压缩..."); (function(img) { var mpImg = new MegaPixImage(img); var resImg = document.createElement("img"); resImg.file = img; mpImg.render(resImg, { maxWidth: 500, maxHeight: 500, quality: 1 }, function() { //do some thing }); })(item); } core.previewImage(item); } },
アップロード処理
1.base64文字列を直接投稿
uploadBase64str: function (base64Str) { var formdata = new FormData(); formdata.append("base64str", base64Str); var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", function (e) { var percentComplete = Math.round(e.loaded * 100 / e.total); para.onProgress(percentComplete.toString() + '%'); }); xhr.addEventListener("load", function (e) { para.uploadComplete(xhr.responseText); }); xhr.addEventListener("error", function (e) { para.uploadError(e); }); xhr.open("post", para.base64strUrl, true); xhr.send(formdata); },
例えば、ここでbase64strUrlは/home/MUploadImgBase64Strで、MVCコントローラーのメソッドは以下の通りです。
りー何 M 個の画像を数十キロバイトまたは数百キロバイトに圧縮できるかというと、もちろん、幅、高さ、品質の設定が小さすぎると、画像が非常に歪んでしまいます。この文字列を取得するにはどうすればよいでしょうか?方法は 2 つあり、1 つは src を直接読み取る方法です:
varbase641 = resImg.src;
もう 1 つはキャンバス変換を使用する方法です:
[HttpPost] public ActionResult MUploadImgBase64Str(string base64str) { try { var imgData = base64str.Split(',')[1]; //过滤特殊字符即可 string dummyData = imgData.Trim().Replace("%", "").Replace(",", "").Replace(" ", "+"); if (dummyData.Length % 4 > 0) { dummyData = dummyData.PadRight(dummyData.Length + 4 - dummyData.Length % 4, '='); } byte[] byteArray = Convert.FromBase64String(dummyData); using (System.IO.MemoryStream ms = new System.IO.MemoryStream(byteArray)) { var img = System.Drawing.Image.FromStream(ms); var path = "~/Content/UploadFiles/mobile/"; var uploadpath = Server.MapPath(path); if (!Directory.Exists(uploadpath)) { Directory.CreateDirectory(uploadpath); } var saveName = uploadpath + “stoneniqiu” + ".jpg"; img.Save(saveName); return Json(saveName); } } catch (Exception e) { return Json(e.Message); } }
同じ画像、両方で取得した文字文字列のサイズが違いますが、画質の違いはわかりません。
たとえば、2M の画像の場合、getBase64Image メソッドを通じて読み取られる文字列のサイズはわずか 64k ですが、src によって直接読み取られるサイズは 270k であり、それぞれによって生成される画像は小さくなります。オリジナル画像(2.2M)、base64(48k)、src(202k)の対応画像は以下の通りです。
getBase64Image は、キャンバスの toDataURL を通じて小さい Base64 文字列を取得します。
2. フロントエンドで BLOB オブジェクトを変換してからバックエンドにポストすることもできます
function getBase64Image(img) { var canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, img.width, img.height); var dataURL = canvas.toDataURL("image/jpeg"); return dataURL; // return dataURL.replace("data:image/png;base64,", ""); } var base64 = getBase64Image(resImg);
3. 圧縮されていない場合は、フォームデータに直接インストールしてバックエンドに送信します。 。
function dataURItoBlob(dataUrl) { var byteString = atob(dataUrl.split(',')[1]); var ab = new ArrayBuffer(byteString.length); var ia = new Uint8Array(ab); for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ab], { type: 'image/jpeg' }); }
以上がこの記事の全内容です。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。
関連する推奨事項:
HTML5 モバイル開発による画像圧縮とアップロード機能の実装
以上がH5は画像圧縮とアップロードを実現しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。