H5 image compression and upload instance,

Source: Internet
Author: User

H5 image compression and upload instance,

After receiving the request, I asked whether the front-end can compress the image? Some images are too large to be compressed on the server. I have never had this experience in consciousness. In the morning, the boss lost a link to zhihu. It seems that the predecessors have already used canvas (shame for their own insights for 3 seconds, now )!.

Canvas Compression

A ready-made library on github is used: https://github.com/stomita/ios-imagefile-megapixel. you have to give a look at stomita. The general idea is to sample and display the image on the canvas, and then use the canvas. toDataURL method to obtain the base64 string for compression. For example, after the input element triggers the change event, read the files in it for operations:

Var fileInput = document. getElementById ('fileinput'); fileInput. onchange = function () {var file = fileInput. files [0]; // create a compressed object, which receives file or blob. Var mpImg = new MegaPixImage (file); // The maxWith, maxHeight, and quality of the render Method determine the quality of the compressed image. var resImg = document. getElementById ('resultimage'); mpImg. render (resImg, {maxWidth: 300, maxHeight: 300, quality: 0.5}) ;}; after compression is completed

Images like this:

The data: image/jpeg format has been applied a lot, and the background images in many styles are directly like this.

It must be noted that there are two points. Here, resImg is a preview image that already exists in the document. If you do not need to preview it, you just create an img for compression (document. createElement ("img"), which has one fewer tagName attribute. You can modify the source code or add this attribute by yourself. The source code is determined based on the tagName. If it does not exist, an error is returned:

MegaPixImage. prototype. render = function (target, options, callback ){//.... target. tagName = target. tagName | "IMG"; // Add this 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 );}};

In addition, this is a time-consuming operation. If multiple images are compressed and cannot be called directly, you need to change the image slightly. Otherwise, the previous image will enter the image after compression.

FileSelected: function () {var files = $ ("# fileImage") [0]. files; var count = files. length; console. log ("Total" + count + "files"); for (var I = 0; I <count; I ++) {var item = files [I]; console. log ("original image size", item. size); if (item. size> 1024*1024*2) {console. log ("the image is larger than 2 MB and starts to be compressed... "); (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 );}},

Upload Processing

1. Direct post base64 string

 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);    },

For example, here base64strUrl is/home/MUploadImgBase64Str. The MVC Controller method is as follows:

[HttpPost] public ActionResult MUploadImgBase64Str (string base64str) {try {var imgData = base64str. split (',') [1]; // filter out special characters to 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. I O. 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 );}}

A few MB of images can be compressed to dozens of k or hundreds of k. Of course, if the width, height, and quality settings are too small, the image will be distorted. How can I obtain this string? There are two methods: one is to directly read src:

Var base641 = resImg. src;

One is to use canvas for conversion:

 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);

The size of the strings obtained from the same image is different, but the quality of the image cannot be distinguished.

For example, for a 2 m image, the size of the string read through the getBase64Image method is 64 k, while the size of the string read by src is 270 k, and the size of the image is smaller. The following figure shows the source image (2.2 M), base64 (48 k), and src (202 k.

GetBase64Image obtains a smaller base64 string through the toDataURL of the canvas.

2. You can also convert the blob object on the front end and then post the object to the backend.

 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' });   }

3. If it is not compressed, it is directly mounted to formdata and sent to the background.

UploadFile: function (file) {console. log ("START upload"); var formdata = new FormData (); formdata. append (para. filebase, file); // This name must be used with the mvc background 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. url, true); xhr. send (formdata );},

All Code: (including compression, upload, and demo ):

Github: https://github.com/stoneniqiu/h5upload/

Summary: this is basically the case. If the front-end can compress images, the traffic and time are indeed saved. The plug-in is improved based on the previous article.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.