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

}
原文地址:https://www.cnblogs.com/tlll/p/8969038.html