js 预处理用户上传图片
前几个月闲得无聊写得一段代码,没想最近刚好用上了,在硬盘里翻了半天找回来,还没好好整理直接用上了
手机用户拍照上传的图片一般都在1M 到4M 之间,如果只是用作头像尺寸就可以缩小很多,1M甚至几M的图转换成几百K。
<!doctype html>
<html>
<head>
<title>test</title>
<script src="js/zepto-master/src/zepto.min.js"></script>
<script>
/*****
by cnblogs.com/ecalf
**/
var uploadImg = (function($){
    function fileUpLoader(config){
        if(typeof(config.field)=='string'){//input type=file
            config.field = document.getElementById(config.field);
        }
        if(typeof(config.viewPane)=='string'){//预览图
            config.viewPane = document.getElementById(config.viewPane);
        }
        if(typeof(config.uploadBtn)=='string'){//上传按钮
            config.uploadBtn = document.getElementById(config.uploadBtn);
        }
        this.afterSelectFile = config.afterSelectFile||function(){};
        this.maxSize = config.maxSize==undefined?4194304:(config.maxSize||0);//maxSize 0 不限制大小 
        this.field = config.field;
        this.viewPane = config.viewPane;
        this.uploadBtn = config.uploadBtn;
        if(config.uploadUrl){
            this.uploadUrl = config.uploadUrl;
        }
        if(typeof(config.afterUpload)=='function'){
            this.afterUpload = config.afterUpload;
        }
        if(Object(config.extParams)===config.extParams){
            this.extParams = config.extParams;
        }
        this.init();
    }
    fileUpLoader.prototype = {
        init:function(){
            this.domEvents();
            console.log('uploadfile init');
        },
        domEvents:function(){
            var host = this;
            if(host.field&&host.afterSelectFile){
                $(host.field).on("change",function(e){
                    host.afterSelectFile&&host.afterSelectFile(this);
                });
            }
            if(host.uploadBtn){
                $(host.uploadBtn).on('click',function(){
                    host.upload();
                });
            }
        },
        imgToDataURL:function(img,type,typecallback,frag){
            type = type||'image/png';
            var databack={
                    status:true,
                    dataURL:'',
                    callback:callback,
                    resolve:function(){
                        this.callback(this.dataURL);
                    }
                }
            var trans = function(pic){//canvas.toDataURL,context.getImageData 不能读取跨域图片
                pic.crossOrigin = "*";
                var cvs = document.createElement("canvas");
                document.body.appendChild(cvs);
                var ctx = cvs.getContext('2d');
                cvs.width = pic.width;
                cvs.height = pic.height;
                console.log('img size:',pic.width+'px',pic.height+'px');
                ctx.drawImage(pic,0,0,pic.width,pic.height);
                var dataURL = cvs.toDataURL(type);
                console.log('dataURL length:',dataURL.length)
                cvs = null;
                ctx = null;
                return dataURL;
            };
            if(!frag&&img.width&&img.height){ //img 加载完才能取出img的数据,如果在domReady 里面执行,图片未加载完会绘制出空白的 canvas
                console.log('trans directly');
                databack.dataURL = trans(img);
                databack.resolve();
            }else{//使用 图片的 natural size,img loaded后才能获得高宽
                databack.status = false;
                var pic = new Image();
                pic.crossOrigin = "*";
                pic.onload = function(e){
                    console.log('trans onload');
                    databack.dataURL = trans(e.target);
                    databack.status = true;
                    databack.resolve();
                    pic = null;
                };
                pic.src = img.src;
            }
            return databack;
        },
        dataURLToBlob:function(dataURL){
            console.log(dataURL.length)
            var type = dataURL.match(/data:(.+?);/);
            type = type?type[1]:'image/png';
            var dataContent = dataURL.replace(/^.+,/,'');
            dataContent = atob(dataContent);
            var dataCharCode = [];
            var i = 0;
            while(i<dataContent.length){
                dataCharCode[i] = dataContent.charCodeAt(i);
                i++;
            }
            var u8Arr = new Uint8Array(dataCharCode);
            return  new Blob([u8Arr],{type:type}); // you maybe use new BolbBuilder() in older browser, maybe canvas.toBlob() is better for image
        },
        readURL:function (input,callback) {//创建预览图
            input = input||this.field;
            if (input.files && input.files[0]) {
                if(this.maxSize&&input.files[0].size > this.maxSize){
                    alert('文件大于'+(this.maxSize/(1024*1024))+'m,请重新上传');
                    return false;
                }
                var reader = new FileReader();
                reader.onload = function (e) {
                    callback&&callback(e.target.result);
                };
                var dataUrl = reader.readAsDataURL(input.files[0]);
                reader = null;
                return dataUrl;
            }
        },
    upload:function(fileConfig){
        var host = this;
        var formData = new FormData();
        var file,name,filename;
        if(!fileConfig){
            name = host.field.name;
             file = host.field.files[0];
             filename = host.field.value.split(/[/\\]/).pop()||"temp.png";
        }else{
            name = fileConfig.name;
             file = fileConfig.file;
             filename = fileConfig.filename||"temp.png";
        }
        if(!file){
            console.log('no file');
        }
        formData.append(name,file,filename);
        if(Object(host.extParams)===host.extParams){
            $.each(host.extParams,function(k,v){
                formData.append(k,v);
            });
        }
        $.ajax({
                url: host.uploadUrl,
                type: 'POST',
                data: formData,
                async: true,
                dataType:'json',
                cache: false,
                contentType: false,
                processData: false,
                timeout:45000,
                success: function (data,status, xhr) {
                    host.afterUpload&&host.afterUpload(data);
                },
                error:function(xhr, errorType, error){
                    console.log(errorType, error);
                },
                complete:function(xhr, status){
                    console.log('post complete,status:',status);
                }
            });
        }//end upload
    };
    return {
        init:function(config){
            return new fileUpLoader(config);
        }
    };
})(Zepto);
$(document).ready(function(){
    upload = uploadImg.init({
        field:'uploadimg',
        viewPane:'viewPane',
        uploadBtn:'submitbtn',
        uploadUrl:'yourimguploadurl.jsp',
        maxSize:0,
        afterUpload:function(resp){ },
        extParams:{uid:12}
    });
    window.onload = function(){
        var img = document.querySelector("img");
        upload.imgToDataURL(img,'image/jpeg',function(DataURL){
            var blob = upload.dataURLToBlob(DataURL);
            console.log(blob);
        },true);
    };
    $("#uploadimg").on("change",function(){
        var file = this.files[0];
        if(!file){ return; }
        upload.readURL(this,function(dataURL){
            upload.viewPane&&(upload.viewPane.src = dataURL);
            var img = new Image();
            img.onload = function(){
                var img = document.querySelector("img");
                upload.imgToDataURL(img,'image/jpeg',function(dataURL){
                    var blob = upload.dataURLToBlob(dataURL);
                    console.log(blob);
                },false);
            }
            img.src=dataURL;
        });
    });
});
</script>
</head>
<body>
<div>
<img id="viewPane" width="800" height="600"  src="img/1111.png" />
<form id="testform">
<!-- camera--照相机;camcorder--摄像机;microphone--录音 -->
<input id="uploadimg" type="file" accept="image/*" capture="camera" />
<input id="submitbtn" type="submit" />
</form>
</div>
</body>
</html>
http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
ios 下 canvas 的 drawImage 存在扭曲 bug (似乎是像素过大时出现),修复方法如下
        /** 修复 ios 下 canvas drawImage 函数的 画面扭曲BUG
         * Detecting vertical squash in loaded image.
         * Fixes a bug which squash image vertically while drawing into canvas for some images.
         * This is a bug in iOS6 devices. This function from  CodeGo.net
         *
         */
        function detectVerticalSquash(img) {
         var iw = img.naturalWidth, ih = img.naturalHeight;
         var canvas = document.createElement('canvas');
         canvas.width = 1;
         canvas.height = ih;
         var ctx = canvas.getContext('2d');
         ctx.drawImage(img, 0, 0);
         var data = ctx.getImageData(0, 0, 1, ih).data;
         // search image edge pixel position in case it is squashed vertically.
         var sy = 0;
         var ey = ih;
         var py = ih;
         while (py > sy) {
          var alpha = data[(py - 1) * 4 + 3];
          if (alpha === 0) {
           ey = py;
          } else {
           sy = py;
          }
          py = (ey + sy) >> 1;
         }
         var ratio = (py / ih);
         return (ratio===0)?1:ratio;
        }
        /**
         * A replacement for context.drawImage
         * (args are for source and destination).
                 *  fixed:  set  height as   height/vertSquashRatio
         */
        function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
         var vertSquashRatio = detectVerticalSquash(img);
         ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
        }
        
IOS 系统 safari 浏览器上开发 应注意的问题:
https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html#//apple_ref/doc/uid/TP40006482-SW15
js 预处理用户上传图片的更多相关文章
- Gremlins.js – 模拟用户随机操作的 JS 测试库
		Gremlins.js 是基于 JavaScript 编写的 Monkey 测试库,支持 Node.js 平台和浏览器中使用.Gremlins.js 随机模拟用户操作:单击窗口中的任意位置,在表格中输 ... 
- Headroom.js – 快速响应用户的页面滚动操作
		Headroom.js 是一个轻量级,高性能的JS插件(无依赖性!),允许你响应用户的滚动行为.Headroom.js 使您能够在适当的时候把元素融入视图,而其它时候让内容成为焦点.Headroom. ... 
- js记录用户在网站的浏览记录和停留时间
		by weber开发者 from http://weber.pub/ 本文地址: http://weber.pub/js记录用户行为浏览记录和停留时间/163.html 问题 公司想统计一个用户从进入 ... 
- JS验证用户真实姓名
		发布:thebaby 来源:脚本学堂 [大 中 小] 本文分享下,使用js代码验证用户真实姓名的方法,有需要的朋友不妨参考下,希望对你有一定的帮助. 原文地址:http://www.jbx ... 
- js记录用户行为浏览记录和停留时间(转)
		演示地址:http://weber.pub/demo/160902/test.html 测试源码下载:http://pan.baidu.com/s/1nvPKbSP 密码:r147 解决问题所使用的知 ... 
- ajaxFileUpload.js 无刷新上传图片,支持多个参数同时上传,支持 ie6-ie10
		/* 131108-xxj-ajaxFileUpload.js 无刷新上传图片 jquery 插件,支持 ie6-ie10 依赖:jquery-1.6.1.min.js 主方法:ajaxFileUpl ... 
- js判断用户是客户端还是移动端
		js判断用户是客户端还是移动端 Javascript 判断客户端是否为 PC 还是手持设备,有时候项目中需要用到,很方便的源生检测,方法一共有两种 1.第一种: function IsPC() { ... 
- Vue.Js的用户体验优化
		一次基于Vue.Js的用户体验优化 一.写在前面 半年以前,第一次在项目上实践VueJs,由于在那之前,没有Angular,avalon等框架的实践经验,所以在Vue的使用上,没有给自己总结出更多 ... 
- JS获取用户的Ip地址
		在网站中通常需要获取使用者的ip地址,获取抵制的方式有很多,这里就简单介绍一下js获取用户ip地址 /*使用的新浪的ip查询api,根据返回的数据进行判断*/ <script src=" ... 
随机推荐
- REPL环境
			一.Node的REPL基本操作 REPL(Read-eval-print-loop):交互式解析器 在REPL环境下,可以定义和运行变量.函数.对象. REPL的常用命令: 进入node,即进入了RE ... 
- Linux中杀不死的进程
			前段时间,一哥们,去杀Linux服务器的进程,发现kill命令失灵了,怎么杀都杀不死. 然后上网查了下资料,原来是要被杀的进程,成为了僵尸进程. 僵尸进程的查看方法: 利用命令ps,可以看到有标记为Z ... 
- [图像]判断图片是PNG还是JPG格式
			typedef NS_ENUM(NSInteger, NSPUIImageType) { NSPUIImageType_JPEG, NSPUIImageType_PNG, NSPUIImageType ... 
- Python爬虫Scrapy框架入门(3)
			往往需要爬取的网页是呈一个树状结构.比如,需要先爬取一个目录,然后再在目录中选择具体的爬取目标.而目录和具体目标之间,网页结构不同,使得我们不能使用相同的爬取策略. 从之前的经验来看,我们对scrap ... 
- 搭建LAMP环境注意事项
			一:安装mysql 5.5以上版本需要使用cmake 和 bison 并且需要安装ncurses 在安装MySQL完毕之后,需要覆盖 掉 /etc/my.cnf centos默认会有一个my.cnf文 ... 
- CNN初步-2
			Pooling 为了解决convolved之后输出维度太大的问题 在convolved的特征基础上采用的不是相交的区域处理 http://www.wildml.com/2015/11/unde ... 
- Redis 外部访问设置
			1.错误原因 Redis搭建好后一般都是使用编程语言进行连接调用,默认Redis的设置是不允许外界访问的,连接Redis只能通过本地(127.0.0.1)来连接,而不能使用网络IP(192.168.1 ... 
- 3 3Sum closest_Leetcode
			Given an array S of n integers, find three integers in S such that the sum is closest to a given num ... 
- JsonHelper MergeJsonTemplate
			namespace Test { using Newtonsoft.Json; using System; using System.Collections.Generic; using System ... 
- 好用的绿色工具(mss2sql,jd-gui)
			1.sql server导入mysql 神器(速度不是一般的快) mss2sql.exe 2.java 反序列化工具 jd-gui.exe 
