{"id":20892835,"url":"https://github.com/commanderxl/imgresize","last_synced_at":"2025-04-06T22:07:31.092Z","repository":{"id":92978625,"uuid":"84741221","full_name":"CommanderXL/imgResize","owner":"CommanderXL","description":"移动端H5图片压缩","archived":false,"fork":false,"pushed_at":"2018-09-30T03:05:14.000Z","size":35,"stargazers_count":402,"open_issues_count":4,"forks_count":85,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-03-30T20:11:46.520Z","etag":null,"topics":["mobile","webview"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CommanderXL.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-03-12T16:46:55.000Z","updated_at":"2024-12-18T18:34:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"c741428a-f08d-4fae-9513-5351890df679","html_url":"https://github.com/CommanderXL/imgResize","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CommanderXL%2FimgResize","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CommanderXL%2FimgResize/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CommanderXL%2FimgResize/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CommanderXL%2FimgResize/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CommanderXL","download_url":"https://codeload.github.com/CommanderXL/imgResize/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247557767,"owners_count":20958047,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mobile","webview"],"created_at":"2024-11-18T10:14:03.868Z","updated_at":"2025-04-06T22:07:31.069Z","avatar_url":"https://github.com/CommanderXL.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 移动端 H5 图片压缩上传\n\n## 安装\n\n* `npm install canvas-resize --save`\n* `UMD`\n\n## 使用\n\n```javascript\nimport canvasResize from 'canvas-resize'\n\ncanvasResize(img, {\n  crop: false,\n  quality: 0.9,\n  rotate: 0,\n  callback(baseStr) {\n    console.log(baseStr.length)\n  }\n})\n```\n\n## 整体思路\n\n大体的思路是，部分 API 的兼容性请参照[caniuse](www.caniuse.com)：\n\n1. 利用[FileReader](https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader),读取`blob对象`,或者是`file对象`，将图片转化为`data uri`的形式。\n2. 使用`canvas`,在页面上新建一个画布,利用`canvas`提供的 API,将图片画入这个画布当中。\n3. 利用`canvas.toDataURL()`，进行图片的压缩，得到图片的`data uri`的值\n4. 上传文件。\n\n步骤 1 当中，在进行图片压缩前，还是对图片大小做了判断的，如果图片大小小于 200KB 时，是直接进行图片上传，不进行图片的压缩，如果图片的大小是大于 200KB，则是先进行图片的压缩再上传:\n\n```javascript\n    \u003cinput type=\"file\" id=\"choose\" accept=\"image/*\"\u003e\n```\n\n```javascript\n    var fileChooser = document.getElementById(\"choose\"),\n        maxSize = 200 * 1024;   //200KB\n    fileChoose.change = function() {\n        var file = this.files[0],   //读取文件\n            reader = new FileReader();\n\n            reader.onload = function() {\n                var result = this.result,   //result为data url的形式\n                    img = new Image(),\n                    img.src = result;\n\n\n                if(result.length \u003c maxSize) {\n                    imgUpload(result);      //图片直接上传\n                } else {\n                    var data = compress(img);    //图片首先进行压缩\n                    imgUpload(data);                //图片上传\n                }\n            }\n\n            reader.readAsDataURL(file);\n    }\n```\n\n步骤 2，3：\n\n```javascript\nvar canvas = document.createElement('canvas'),\n  ctx = canvas.getContext('2d')\n\nfunction compress(img) {\n  canvas.width = img.width\n  canvas.height = img.height\n\n  //利用canvas进行绘图\n\n  //将原来图片的质量压缩到原先的0.2倍。\n  var data = canvas.toDataURL('image/jpeg', 0.2) //data url的形式\n\n  return data\n}\n```\n\n在利用 canvas 进行绘图的过程中,IOS 图片上传过程中，存在着这样的问题：\n\n1. 当你竖着拿手机的时候，拍完照，上传图片时，会出现照片自动旋转的情况，而横着拍照并上传图片时不会出现这个问题。这个时候如果想纠正图片自动旋转的情况，将图片转化为二进制的数据`(使用了binaryajax.js)`，方便获取图片的`exif信息`，通过获取`exif的信息`来确定图片旋转的角度`(使用了exif.js)`，然后再进行图片相应的旋转处理。[解决方法请戳我](http://bbs.it-home.org/thread-55474-1-1.html)\n2. 在`IOS`中，当图片的大小大于 2MB 时，会出现图片压扁的情况，这个时候需要重置图片的比例。[解决方法请戳我](http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios)\n3. 利用 FileReader，读取图片的过程需要花费一定时间,将图片数据注入到 canvas 画布中需要一定时间，图片压缩的过程中，图片越大，CPU 计算消耗的时间也越长，可能会出现顿卡的情况。总之，就是这个过程当中需要花费一定时间。\n4. IOS8.1 的版本中有个`FileReader`的 bug: `FileReader`读取的图片转化为 Base64 时，字符串为空，[具体的问题描述请戳我](http://stackoverflow.com/questions/25999083/filereader-not-working-on-ios-8), 遇到这个情况的话- - 还是老老实实把图片不做压缩处理扔给服务端吧.\n\n步骤 4,文件上传有 2 种方式:\n\n1. 将图片转化为`base64`\n2. 将图片数据转为`Blob对象`，使用`FormData`上传文件\n\n方式 1 可以通过`xhr ajax`或者`xhr2 FormData`进行提交。\n\n方法 2 这里就有个大坑了。[具体描述请戳我](https://code.google.com/p/android/issues/detail?id=39882)\n\n简单点说就是：`Blob对象`是无法注入到`FormData对象`当中的。\n\n当你拿到了图片的`data uri数据`后，将其转化为`Blob`数据类型\n\n```javascript\nvar ndata = compress(img)\nndata = window.atob(ndata) //将base64格式的数据进行解码\n\n//新建一个buffer对象，用以存储图片数据\nvar buffer = new Uint8Array(ndata.length)\nfor (var i = 0; i \u003c text.length; i++) {\n  buffer[i] = ndata.charCodeAt(i)\n}\n\n//将buffer对象转化为Blob数据类型\nvar blob = getBlob([buffer])\n\nvar fd = new FormData(),\n  xhr = new XMLHttpRequest()\nfd.append('file', blob)\n\nxhr.open('post', url)\nxhr.onreadystatechange = function() {\n  //do something\n}\nxhr.send(fd)\n```\n\n在新建`Blob对象`中有需要进行兼容性的处理，特别是对于不支持`FormData`上传`blob`的 andriod 机的兼容性处理。[具体的方法请戳我](https://github.com/gokercebeci/canvasResize)\n主要实现的细节是通过重写 HTTP 请求。\n\n---\n\n## 2 月 19 日更新\n\n在安卓机器中, 部分机型不支持`JPEG`格式的图片导出, 在`fex-team`提供的`webuploader`插件当中有个`jpegencoder.js`和`androidpatch.js`插件主要是解决这个问题, [链接请戳我](https://github.com/fex-team/webuploader/blob/master/src/runtime/html5/androidpatch.js)，不过在部分`4.x`的机型, 在`webview`里面对`file`对象进行了阉割，比如你拿不到`file.type`的值。 唉- -。\n\n## 2 月 22 日更新\n\n`Android4.4`下`\u003cinput type=\"file\"\u003e`由于系统`WebView`的`openFileChooser`接口更改，导致无法选择文件，从而导致无法上传文件. [bug 描述请戳我](https://code.google.com/p/android/issues/detail?id=62220)\n\n## 使用\n\n```javascript\n  npm install\n  npm run build\n```\n\n- 支持 AMD, CMD 模块化的引入方式\n- 也可通过外链\n\n```javascript\ncanvasResize(this.files[0], {\n  crop: false, // 是否裁剪\n  quality: 0.9, // 压缩质量  0 - 1\n  rotate: 0, // 旋转角度\n  callback(baseStr) {\n    console.log(baseStr.length)\n  }\n})\n```\n\n## Some Tips\n\n- 在使用`FormData`进行文件上传的时候，没有将图片文件转化为`blob`，而是转为了`base64`，主要是考虑到部分机型的兼容性的问题。\n- 在遇到一些是由于`native`端上导致的问题的时候，比如在安卓`4.4.x`的部分机型(主要集中在原生的系统，部门国产机，对`openFileChooser`做过兼容)当中无法唤起选择图片或拍照的接口,\n  这个时候还是让`native`的同学给你提供`bridge`去完成图片的压缩和转码吧, 然后你再拿着端上给压缩好的图片去上传吧。\n- 封装好的库中没有提供裁剪的选项，如果需要有这方面的需求，请在`src/canvasResize.js`里面做相应的修改(读读源码也挺好- -)。\n\n## 使用到的库\n\n- [binaryajax.js](https://github.com/jseidelin/binaryajax)\n- [canvasResize.js](https://github.com/gokercebeci/canvasResize)\n- [exif.js](https://github.com/exif-js/exif-js)\n- [andriodpatch.js](https://github.com/fex-team/webuploader/blob/master/src/runtime/html5/androidpatch.js)\n- [jpegencoder.js](https://github.com/fex-team/webuploader/blob/master/src/runtime/html5/jpegencoder.js)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcommanderxl%2Fimgresize","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcommanderxl%2Fimgresize","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcommanderxl%2Fimgresize/lists"}