zoukankan      html  css  js  c++  java
  • js等比压缩上传

    一、js文件,这个是封装过的,借用了网络上的代码然后修改的

    (function(window,undefined){
        
        var upload = function(){
            this.init();
        };
        
        upload.prototype={
            init:function(){
                var inputDom = document.createElement("input");
                inputDom.type = "file";
                inputDom.setAttribute("accept","image/*");
                inputDom.setAttribute("multiple","multiple");
                this.inputDom = inputDom;
                this.bindChange();
            },
            start:function(o){
                this.opt = this.setOpt(o);
                this.inputDom.value = "";
                this.canvasBefore();
                this.inputDom.click();
            },
            bindChange:function(){
                var dom = this.inputDom;
                var that = this;
                 dom.onchange = function() {
                     try{
                         
                        if (!this.files.length) return;
                        var files = Array.prototype.slice.call(this.files);
                        if (files.length > 1) {
                            alert("最多只可上传1张图片");
                            return;
                        }
                        
                        _shade_layer.show("上传中,请稍后...");
                        files.forEach(function(file, i) {
                            if (!//(?:jpeg|png|gif)/i.test(file.type)) return;
                            var reader = new FileReader();
                    
                            //获取图片大小
                            var size = file.size / 1024 > 1024 ? (~~ (10 * file.size / 1024 / 1024)) / 10 + "MB": ~~ (file.size / 1024) + "KB";
                            
                            reader.onload = function() {
                                var result = this.result;
                                var img = new Image();
                                img.src = result;
                                
                                //超出大小
                                if(result.length > that.opt.maxSize){
                                    alert("图片大小不能超过5M");
                                    _shade_layer.hide();
                                    return;
                                }
                                
                                //如果图片大小小于100kb,则直接上传
                                if (result.length <= that.opt.minSize) {
                                    img = null;
                                    that.upload(result, file.type);
                                    return;
                                }
                                //图片加载完毕之后进行压缩,然后上传
                                if (img.complete) {
                                    callback();
                                } else {
                                    img.onload = callback;
                                }
                                function callback() {
                                    var data = that.compress(img);
                                    that.upload(data, file.type);
                                    img = null;
                                }
                            };
                            reader.readAsDataURL(file);
                        })
                        
                     }catch(e){
                         _shade_layer.hide();
                         alert("上传出现错误");
                         return ;
                     }
                };
            },
            /**
             * 绘制压缩图片的canvas
             */
            canvasBefore:function(){
                var canvasDom = document.getElementById("canvas_id");
                if(canvasDom){canvasDom.parent().remove();}
                
                var tCanvasDom = document.getElementById("tCanvas_id");
                if(tCanvasDom){tCanvasDom.parent().remove();}
                
                //用于压缩图片的canvas
                var canvas = document.createElement("canvas");
                canvas.id = "canvas_id";
                this.canvas = canvas;
                this.ctx = canvas.getContext('2d');
                
                //瓦片canvas
                var tCanvas = document.createElement("canvas");
                tCanvas.id = "tCanvas_id";
                this.tCanvas = tCanvas;
                this.tctx = tCanvas.getContext("2d");
            },
            /**
             * 使用canvas对大图片进行压缩
             * @param {} img   图片对象
             * @return {}
             */
            compress:function(img) {
                var canvas = this.canvas;
                var tCanvas = this.tCanvas;
                var tctx = this.tctx;
                var ctx = this.ctx;
                
                var initSize = img.src.length;
                var width = img.width;
                var height = img.height;
            
                //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
                var ratio;
                if ((ratio = width * height / 4000000) > 1) {
                    ratio = Math.sqrt(ratio);
                    width /= ratio;
                    height /= ratio;
                } else {
                    ratio = 1;
                }
                canvas.width = width;
                canvas.height = height;
            
                //铺底色
                ctx.fillStyle = "#fff";
                ctx.fillRect(0, 0, canvas.width, canvas.height);
            
                //如果图片像素大于100万则使用瓦片绘制
                var count;
                if ((count = width * height / 1000000) > 1) {
                    count = ~~ (Math.sqrt(count) + 1); //计算要分成多少块瓦片
                    //计算每块瓦片的宽和高
                    var nw = ~~ (width / count);
                    var nh = ~~ (height / count);
                    tCanvas.width = nw;
                    tCanvas.height = nh;
                    for (var i = 0; i < count; i++) {
                        for (var j = 0; j < count; j++) {
                            tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
                            ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
                        }
                    }
                } else {
                    ctx.drawImage(img, 0, 0, width, height);
                }
                
                //进行最小压缩
                var ndata = canvas.toDataURL('image/jpeg', this.opt.proportion);
                /*
                console.log('压缩前:' + initSize);
                console.log('压缩后:' + ndata.length);
                console.log('压缩率:' + ~~ (100 * (initSize - ndata.length) / initSize) + "%");
                */
                tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
                
                this.canvas = canvas;
                this.tCanvas = tCanvas;
                this.tctx = tctx;
                this.ctx = ctx;
                return ndata;
            },
            /**
               * 获取blob对象的兼容性写法
               * @param buffer
               * @param format
               * @returns {*}
               */
            getBlob:function(buffer, format) {
                try {
                    return new Blob(buffer, {
                        type: format
                    });
                } catch(e) {
                    var bb = new(window.BlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder);
                    buffer.forEach(function(buf) {
                        bb.append(buf);
                    });
                    return bb.getBlob(format);
                }
            },
            /**
             * 获取formdata
             * @return {}
             */
            getFormData:function() {
                var isNeedShim = ~navigator.userAgent.indexOf('Android') && ~navigator.vendor.indexOf('Google') && !~navigator.userAgent.indexOf('Chrome') && navigator.userAgent.match(/AppleWebKit/(d+)/).pop() <= 534;
                return isNeedShim ? new this.FormDataShim() : new FormData();
            },
            /**
             * formdata 补丁, 给不支持formdata上传blob的android机打补丁
             */
            FormDataShim:function() {
                var o = this,
                parts = [],
                boundary = Array(21).join('-') + ( + new Date() * (1e16 * Math.random())).toString(36),
                oldSend = XMLHttpRequest.prototype.send;
                this.append = function(name, value, filename) {
                    parts.push('--' + boundary + '
    Content-Disposition: form-data; name="' + name + '"');
                    if (value instanceof Blob) {
                        parts.push('; filename="' + (filename || 'blob') + '"
    Content-Type: ' + value.type + '
    
    ');
                        parts.push(value);
                    } else {
                        parts.push('
    
    ' + value);
                    }
                    parts.push('
    ');
                };
            
                // Override XHR send()
                XMLHttpRequest.prototype.send = function(val) {
                    var fr, data, oXHR = this;
                    if (val === o) {
                        // Append the final boundary string
                        parts.push('--' + boundary + '--
    ');
                        // Create the blob
                        data = getBlob(parts);
                        // Set up and read the blob into an array to be sent
                        fr = new FileReader();
                        fr.onload = function() {
                            oldSend.call(oXHR, fr.result);
                        };
                        fr.onerror = function(err) {
                            throw err;
                        };
                        fr.readAsArrayBuffer(data);
                        // Set the multipart content type and boudary
                        this.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
                        XMLHttpRequest.prototype.send = oldSend;
                    } else {
                        oldSend.call(this, val);
                    }
                };
            },
            /**
             * 图片上传,将base64的图片转成二进制对象,塞进formdata上传
             * @param {} basestr  
             * @param {} type
             * @param {} $li
             */
            upload:function(basestr, type) {
                var that = this;
                var text = window.atob(basestr.split(",")[1]);
                var buffer = new Uint8Array(text.length);
                var pecent = 0,
                loop = null;
                for (var i = 0; i < text.length; i++) {
                    buffer[i] = text.charCodeAt(i);
                }
                var blob = this.getBlob([buffer], type);
                var xhr = new XMLHttpRequest();
                var formdata = this.getFormData();
                formdata.append('imagefile', blob);
                xhr.open('post', this.opt.uploadURL);
                xhr.onreadystatechange = function() {
                    this.canvas = null;
                    this.tCanvas = null;
                    this.tctx = null;
                    this.ctx = null;
                    
                    var func = that.opt.callBackFunc;
                    var id = that.opt.id;
                    
                    var oDataObj = that.opt.oDataObj;
                    var nType = that.opt.nType;
                    var frameCallBackFunc = that.opt.frameCallBackFunc;
                    var strCallbackFunc = that.opt.strCallbackFunc;
                    oDataObj["strCallbackFunc"] = strCallbackFunc;
                    oDataObj["nType"] = nType;
                    
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        var url = xhr.responseText || "";
                        console.log(url);
                        var nState = url.length == 0 ? -1 : 0;
                        var strMsg = url.length == 0 ? "上传失败" : url;
                        oDataObj["nState"] = nState;
                        oDataObj["strMsg"] = strMsg;
                        oDataObj = JSON.stringify(oDataObj);
                        eval(frameCallBackFunc+"('"+oDataObj+"')");
                        _shade_layer.hide();
                    }
                    
                    if(xhr.status != 200){
                        oDataObj["nState"] = -1;
                        oDataObj["strMsg"] = "上传失败";
                        oDataObj = JSON.stringify(oDataObj);
                        eval(frameCallBackFunc+"('"+oDataObj+"')");
                        _shade_layer.hide();
                    }
                };
                xhr.send(formdata);
            
            },setOpt:function(o){
                var defaultOptions={  
                        nType:'',             //回调的不同类型,通过这个类型来改_plus.callbackuploadPicture里面对于回调的具体方法,其实主要就是控制最终回调函数的参数
                        minSize:100 * 1024,  //最小为100kb,也就是说100kb以下的不压缩直接上传
                        maxSize:1024 * 1024 * 5,  //最大为10M,也就是说100kb以下的不压缩直接上传
                        proportion:0.3,    //压缩比例:从0-1之间
                        strCallbackFunc:'',
                        frameCallBackFunc:'',
                        oDataObj:{},
                        uploadURL:'http://pocketwap.xxx.com/Servlet/fileUpload.svl'
                    };    
                    if(o && Object.prototype.toString.call(o)=='[object Object]')
                    {
                        for(var k in o)
                        {
                            defaultOptions[k]= typeof o[k]==='undefined' ? defaultOptions[k] : o[k];
                        }
                    }
                    return defaultOptions; 
            }
        }
        
        window.upload=upload;
    })(window,undefined)
    
    var _upload = new upload();

    二、js页面使用如下:

    _upload.start({
    	id:Id,
    	callBackFunc:strCallbackFunc  //回调地址
    });

    三、服务端接收,这边因为是要统一上传到文件服务器,所以这里中转了一下,如果不需要中转,直接就可以在这里面处理就行

    package com.xxx.businesscenter.web;
    
    import java.io.BufferedInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileUploadException;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import org.apache.log4j.Logger;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.cdoframework.cdolib.base.UUidGenerator;
    
    /**
     * Servlet implementation class FileUploadServlet
     */
    public class FileUploadServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
        private Logger log=Logger.getLogger(ApplicationListener.class);   
        /**
         * @see HttpServlet#HttpServlet()
         */
        public FileUploadServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // TODO Auto-generated method stub
            this.doPost(request, response);
        }
    
        /**
         * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // TODO Auto-generated method stub
            
            String strResult = "";
            DiskFileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload(factory);
            try {
                List<FileItem> items = upload.parseRequest(request);
                if(items.size() > 0 ){
                    FileItem item = items.get(0);
                    if(!item.isFormField()){
                        strResult = uploadFile(item);
                    }
                }
            } catch (FileUploadException e) {
                 log.info(e);
            }
            
            response.getWriter().print(strResult);
            
        }
        
        private String uploadFile(FileItem item) {
            String contentType = item.getContentType();
            String postfix = contentType.split("/")[1];
            String result = "";
            String end = "
    ";
            String twoHyphens = "--";
            String boundary = "*****";
            String newName = UUidGenerator.genenator() + "."+postfix;
            String actionUrl = "http://file.xxx.com.cn/Servlet/fileUpload.svl";
            BufferedInputStream bufin = null;
            InputStream is = null;
            try {
              URL url = new URL(actionUrl);
              HttpURLConnection conn = (HttpURLConnection) url.openConnection();
              conn.setConnectTimeout(10000);   //超时时间为10秒
              conn.setDoInput(true);
              conn.setDoOutput(true);
              conn.setUseCaches(false);
              conn.setRequestMethod("POST");
              conn.setRequestProperty("Connection", "Keep-Alive");
              conn.setRequestProperty("Charset", "UTF-8");
              conn.setRequestProperty("Content-Type","multipart/form-data;boundary=" + boundary);
              DataOutputStream ds = new DataOutputStream(conn.getOutputStream());
              ds.writeBytes(twoHyphens + boundary + end);
              ds.writeBytes("Content-Disposition: form-data; " + "name="file1";filename="" + newName + """ + end);
              ds.writeBytes("Content-Type:" + contentType + "
    
    ");
              
              bufin = new BufferedInputStream(item.getInputStream());
              int bufferSize = 2048;
              byte[] buffer = new byte[bufferSize];
              int length = -1;
              while ((length = bufin.read(buffer)) != -1) {
                ds.write(buffer, 0, length);
              }
              ds.writeBytes(end);
              ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
              bufin.close();
              ds.flush();
              
              //获取上传返回结果
              int code = conn.getResponseCode();
              is = conn.getInputStream();
              int ch;
              StringBuffer b = new StringBuffer();
              while ((ch = is.read()) != -1) {
                b.append((char) ch);
              }
              
              String str = b.toString();
              log.info("-------------------------"+str);
              if (conn.getResponseCode() == 200) {
                  if(str.length() > 0 ){
                      JSONObject jObject = JSON.parseObject(str);
                      String strFilePath = (String) jObject.get("strFilePath");
                      String strFileName = (String) jObject.get("strFileName");
                      result = strFilePath+strFileName;
                      log.info("-------------------------图片上传地址="+result);
                  }
              }else{
                  log.info("-------------------------上传失败code="+code);
              }
              
            } catch (Exception e) {
                log.info(e);
                return result;
            }finally{
                try {
                    if(bufin!=null){
                        bufin.close();
                    }
                    if(is!=null){
                        is.close();
                    }
                } catch (IOException e) {
                    log.info("-------------------------流关闭失败-------------------------");
                    e.printStackTrace();
                }
            }
            return result;
        }
        
    
    }
  • 相关阅读:
    Android 目前最稳定和高效的UI适配方案
    很值得收藏的安卓开源控件库
    django-初始配置(纯手写)
    面向对象 继承
    wsgiref手写一个web服务端
    socket手写一个简单的web服务端
    vue指令
    vue入门
    python中and,or
    面向对象三大特性-继承
  • 原文地址:https://www.cnblogs.com/tlll/p/8969038.html
Copyright © 2011-2022 走看看