先上效果

上传图片后(设置了最多上传3张图片,三张后上传按钮消失)

点击图片放大,可以使用删除和旋转按钮 (旋转功能主要是因为ios手机拍照后上传会有写图片被自动旋转,通过旋转功能可以调正)

html页面

需要引入weui.min.css 不然没法渲染样式, 将下面的代码放在需要上传文件的地方就行了,如果不需要图片旋转功能, 可以直接删掉那个div, 改不改js无影响

addPhoto.html

 <!--图片缩略图-->
         <div class="weui-cells weui-cells_form" style="margin-top:0px;">
                <div class="weui-cell">
                      <div class="weui-cell__bd">
                        <div class="weui-uploader">
                            <div class="weui-uploader__hd">
                                    <p class="weui-uploader__title" style="font-size: 14px;">照片:</p>
                                 <div class="weui-uploader__info"><span id="curNum">0</span>/3</div>
                            </div>
                            <div class="weui-uploader__bd">
                                <ul class="weui-uploader__files" id="uploaderFiles"></ul> <!--缩略图显示-->
                                <div class="weui-uploader__input-box">
                                        <form action="" id="upBox_add" onsubmit="return false;">
                                        <input id="uploaderInput" name="file" class="weui-uploader__input zjxfjs_file" type="file"  capture="camera" accept="image/png,image/jpg,image/gif,image/JPEG" multiple=""></input>
                                     </form>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
         <!--放大图片显示-->
          <div class="weui-gallery" id="gallery">
                  <span class="weui-gallery__img" id="galleryImg" style="bottom: 12%;"></span>
                  <div class="weui-gallery__opr" style="width:50%;">
                    <a href="javascript:" class="weui-gallery__del">
                        <i class="weui-icon-delete weui-icon_gallery-delete"></i>
                    </a>
                </div>
                 <!-- 图片旋转按钮-->
                 <div class="weui-gallery__opr2" style="z-index: 1200;width:50%;position: absolute;bottom:0;right:0;background-color: #0d0d0d;color: #fff;line-height: 60px;text-align: center;">
                    <a href="javascript:" class="weui-gallery__rot">
                        <img src="/images/report/rotate.png" style="vertical-align: middle;"/>
                    </a>
                 </div>
         </div>

   <!--图片上传时, 给出上传提示, 并且不可操作数据, 上传完成去掉提示-->     <div id="loading" style="display:none; width:100%;height:100%;position:absolute;opacity: 0.5;z-index: 1001;">          <div id="inner" style="display:none;width:22%; position:absolute; left:45%; top:33%;font-size: 16px;font-weight: bold;">                     <p>正在上传...</p>          </div>     </div>

然后在addPhoto.js中调用上传图片的方法(上传图片的方法写在了另一个js中)

addPhoto.js

var data={  imgPathList:[],  imgPath:'',  imgNum:0,//原有图片的数量,会根据删除而减少,新增的值为0  imgArr:null  }var add = {
    template: '#add',
    data: function(){
        return data;
    },
    created: function () {
        var self = this;
    },
    mounted:function(){//判断当前操作系统是安卓还是ios , 电脑浏览器使用可以去掉这个判断,加上也不影响
        var u = navigator.userAgent,
        app = navigator.appVersion;

        var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;
        var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); 

        if (isAndroid) {
            $("#upBox_add").find("input[type='file']").attr("capture","camera");
        }
        if (isIOS) {
            $("#upBox_add").find("input[type='file']").removeAttr("capture");
        }

    },
    methods: {      loadingOpen:function () {             $('#loading').css('display','block');             $('#inner').css('display','block');//显示上传提示         },         loadingClose:function () {             $('#loading').css('display','none');             $('#inner').css('display','none');         },
         upload:function () {                uploadImg("/xxx/xxx");//传的参数是图片上传的接口, 用于ajax上传
         },         addToDB:function(){          if(0 != addReport_data.imgPathList.length){                     data.imgPath = data.imgPathList.join(",");                }              //我这里用的是vue的框架,根据自己的框架修改保存到数据库的方法        Vue.resource("xxxx).save(data).then(function(response){                               });         }
}

图片上传的js

upload.js

Array.prototype.indexOf = function(val) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == val) return i;
    }
    return -1;
};
Array.prototype.removeVal = function(val) {
    var index = this.indexOf(val);
    if (index > -1) {
        this.splice(index, 1);
    }
};
/**
 三个参数
 file:一个是文件(类型是图片格式),
 w:一个是文件压缩的后宽度,宽度越小,字节越小
 objDiv:一个是容器或者回调函数
 photoCompress()
 */
function photoCompress(file,w,objDiv){
    var reader=new FileReader();
    /*开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/
    reader.readAsDataURL(file);
    reader.onloadend=function(e){
        var re=this.result;
        canvasDataURL(re,w,objDiv);
    }
}
function canvasDataURL(path, obj, callback){
    var img = new Image();
    img.src = path;
    img.onload = function(){
        var that = this;
        // 默认按比例压缩
        var w = that.width,
            h = that.height,
            scale = w / h;
        w = obj.width || w;
        h = obj.height || (w / scale);
        var quality = 0.7;  // 默认图片质量为0.7
        //生成canvas
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        // 创建属性节点
        var anw = document.createAttribute("width");
        anw.nodeValue = w;
        var anh = document.createAttribute("height");
        anh.nodeValue = h;
        canvas.setAttributeNode(anw);
        canvas.setAttributeNode(anh);
        ctx.drawImage(that, 0, 0, w, h);
        // 图像质量
        if(obj.quality && obj.quality <= 1 && obj.quality > 0){
            quality = obj.quality;
        }
        // quality值越小,所绘制出的图像越模糊
        var base64 = canvas.toDataURL('image/jpeg', quality);
        // 回调函数返回base64的值
        callback(base64);
    }
}
/**
 * 将以base64的图片url数据转换为Blob
 * @param urlData
 * 用url方式表示的base64图片数据
 */
function convertBase64UrlToBlob(urlData){
    var arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    var b = new Blob([u8arr], {type:mime});
    return b;
}

var uploadImg="";
$(function() {
    var files;
    var filearr = [];
    var allImgSize=0;
    var tmpl = '<li class="weui-uploader__file" style="background-image:url(#url#)"></li>',
        $gallery = $("#gallery"),
        $galleryImg = $("#galleryImg"),
        $uploaderInput = $("#uploaderInput"),
        $uploaderFiles = $("#uploaderFiles");

    //选好图片触发
    $uploaderInput.on("change", function(e) {
        var src, url = window.URL || window.webkitURL || window.mozURL;
        files = e.target.files;
        if(files.length > 3){//一次最多上传3张图片
            alert("图片数量大于3张,请重新选择!");
            return;
        }
        if((filearr.length + files.length) <= 3){//判断所选的总图片数是否不大于3, 大于3张不能上传
            var curNum =$("#curNum");
            var vehLen=0;
            if(addReport_data.imgArr!=null){
                vehLen=addReport_data.imgArr.length;
            }
            for(var i = 0, len = files.length, end = len-1; i < len; i++) {

                var curI=i;
                var imgSize = files[i].size;
                if(imgSize>1024*1024*5){//大于5M给出提示
                    alert("上传的第"+(i+1)+"张图片超过了5M!");
                    continue;
                }else{
                    //压缩开始
                    var fileObj=files[i];
                   if(fileObj.size/1024 > 1025) { //大于1M,进行压缩上传
                        photoCompress(fileObj, {
                            quality: 0.1
                        }, function(base64Codes){
                            var bl = convertBase64UrlToBlob(base64Codes);
                            var form = new FormData();
                            form.append("file", bl,Date.parse(new Date())+".jpg");//将压缩后的图片编程文件对象
                            allImgSize+=bl.size;
                            if(bl.size/1024 < 1024){
                                filearr.push(form.get("file"));
                            }
                            if(curI==end){
                                curNum.text(vehLen+filearr.length);
                            }
                            form.delete("file");//删除存入的压缩后的文件对象, 保证每次压缩只有当前被压缩的对象
                        });
                    }else{ //小于等于1M 原图上传
                        filearr.push(files[i]);
                        allImgSize+=files[i].size;
                    }
                    //压缩结束

                    if(url) {
                        src = url.createObjectURL(fileObj);
                    } else {
                        src = e.target.result;
                    }
                    $uploaderFiles.append($(tmpl.replace('#url#', src)));
                }
            }
            curNum.text(vehLen+filearr.length);
            if(filearr.length == 3){//如果已经选择了3张图片,隐藏上传按钮
                $('.weui-uploader__input-box').css('display','none');
            }
         }else{
             alert("图片总数超过3张,请重新选择!");
             return;
         }
    });

    var index; //第几张图片
    var current = 0;//旋转多少度
    $uploaderFiles.on("click", "li", function() {
        index = $(this).index();
        $galleryImg.attr("style", this.getAttribute("style"));
        $gallery.fadeIn(100);
        current = 0;
    });

    $galleryImg.on("click", function() {
        $gallery.fadeOut(100);
    });

    //图片旋转
    $(".weui-gallery__opr2").click(function() {
        current += 90;
        $("#galleryImg").css('transform', 'rotate(' + current + 'deg)');
    });

    //删除图片
    $(".weui-gallery__del").click(function() {
        $("#upBox_add").find('input').val('');//每次删除图片后,置空input框
        //$uploaderInput.attr('type','text');//第二种方法,更改input的属性, 实现重复上传
        var num=index-addReport_data.imgNum;
        allImgSize-=filearr[num].size;
        filearr.splice(num, 1);//删除刚新增的图片,如果是新增的,原有图片(vehiclePicNum)为0
        $uploaderFiles.find("li").eq(index).remove();
        var vehLen=0;
        if(data.imgArr!=null){
            vehLen=data.imgArr.length;
        }
        $("#curNum").text(vehLen+filearr.length);
        if(filearr.length < 3){//判断删除后,上传图片是否不大于3, 不大于,显示上传按钮
            $('.weui-uploader__input-box').css('display','block');
        }
        $gallery.fadeOut(100);

    });

    uploadImg=function(upUrl) {
        if(filearr.length>0){
            if(filearr.length<=3){
                var imgList = new FormData($("#upBox_add")[0]);  //formData提交
                imgList.delete("file");
                for(var i =0;i<filearr.length;i++){
                    imgList.append("file", filearr[i]);
                }
                //上传所有的图片
                if(allImgSize<1024*1024*10){
                    add.methods.loadingOpen();//上传中
                    submitPicture(upUrl, imgList);
                }else{
                    alert("上传图片的总大小不能超过10M!");
                }

            }else{
                alert("最多只能上传3张照片!");
                return false;
            }
        }else{//如果没有选择图片
            add.methods.addToDB();
        }
    }
});

//上传(将文件流数组传到后台)
function submitPicture(url,data) {

    $.ajax({
        type: "post",
        url: url,
        async: true,
        data: data,
        //下面这两个要写成false,要不然上传不了。
        processData: false,
        contentType: false,
        success: function(response) {//我这里上传接口返回的是json字符串,所以转成了对象后通过for循环将图片url存到数组中,方便html循环展示         response = JSON.parse(response);var reArray=response.data;
                for(var i=0;i<reArray.length;i++){
                    data.imgPathList[i] = reArray[i].src;
                }
                add.methods.loadingClose();//关闭上传提示
                add.methods.addToDB();//调用保存方法,添加到数据库
       },
        error: function(xhr) {
        }
    });

}

其中使用了FormData对象, 具体用法请看:https://www.cnblogs.com/gczmn/p/9437935.html

以上js都是经过删减的, 去掉了多余的东西, 可能会有一些遗漏, 通过调试基本都能解决

html + js 实现图片上传,压缩,预览及图片压缩后得到Blob对象继续上传问题的更多相关文章

  1. 移动端 H5 拍照 从手机选择图片,移动端预览,图片压缩,图片预览,再上传服务器

    前言:最近公司的项目在做全网营销,要做非微信浏览器的wap 站 的改版,其中涉及到的一点技术就是采用H5 选择手机相册中的图片,或者拍照,再将获取的图片进行压缩之后上传. 这个功能模块主要有这5点比较 ...

  2. input type=file实现图片上传,预览以及图片删除

    背景 前两天在做一个PC网站的意见反馈,其中涉及到了图片上传功能,要求可以上传多张图片,并且支持图片上传预览及图片删除, 图片上传这一块以前没怎么搞过,而且一般也很少会碰到这样的需求,所以在做这个功能 ...

  3. 小程序实现图片上传,预览以及图片base64位处理

    最近一段时间在做小程序项目,第一期功也完工了.需要好好总结一下经验,把项目中遇到的问题好好总结一下,遇到的问题,踩过的坑.今天写一个小程序实现图片上传,预览,以及删除,图片base64位处理.下面就是 ...

  4. js 点击文本框,预览选择图片

    点击文件选择框,选择图片文件,通过FileReader对象,读取图片文件中的内容,存放于result中,具体代码如下 <input type="file" onchange= ...

  5. html之file标签 --- 图片上传前预览 -- FileReader

    记得以前做网站时,曾经需要实现一个图片上传到服务器前,先预览的功能.当时用html的<input type="file"/>标签一直实现不了,最后舍弃了这个标签,使用了 ...

  6. file标签 - 图片上传前预览 - FileReader &amp; 网络图片转base64和文件流

    记得以前做网站时,曾经需要实现一个图片上传到服务器前,先预览的功能.当时用html的<input type="file"/>标签一直实现不了,最后舍弃了这个标签,使用了 ...

  7. 【转】html之file标签 --- 图片上传前预览 -- FileReader

    记得以前做网站时,曾经需要实现一个图片上传到服务器前,先预览的功能.当时用html的<input type="file"/>标签一直实现不了,最后舍弃了这个标签,使用了 ...

  8. js实现图片上传及预览----------------------&gt;&gt;兼容ie6-8 火狐以及谷歌

    <head runat="server"> <title>图片上传及预览(兼容ie6/7/8 firefox/chrome)</title> & ...

  9. vue开发中vue-resource + canvas 图片压缩、上传、预览

    1.使用vue-resource上传,也可以自定义ajax上传: 2.使用<input type="file" @change="submit()" na ...

随机推荐

  1. java并发编程(十八)阻塞队列和阻塞栈

    阻塞队列 阻塞队列是Java 5并发新特性中的内容,阻塞队列的接口是java.util.concurrent.BlockingQueue,它有多个实现类:ArrayBlockingQueue.Dela ...

  2. .NET轻量级MVC框架:Nancy入门教程(二)——Nancy和MVC的简单对比

    在上一篇的.NET轻量级MVC框架:Nancy入门教程(一)——初识Nancy中,简单介绍了Nancy,并写了一个Hello,world.看到大家的评论,都在问Nancy的优势在哪里?和微软的MVC比 ...

  3. Scala implicit

    Scala implicit implicit基本含义 在Scala中有一个关键字是implicit, 之前一直不知道这个货是干什么的,今天整理了一下. 我们先来看一个例子: def display( ...

  4. querySelectorAll

    <!DOCTYPE html><html><body> <div id="query">第一个</div> <di ...

  5. python2 与 python3的区别

    python2 与 python3的区别 几乎所有的python2程序都需要一些修改才能正常的运行在python3的环境下.为了简化这个转换过程,Python3自带了一个2to3的实用脚本.这个脚本会 ...

  6. dialog 关闭 清除

    div.dialog({ close: function () { $(this).dialog('destroy').remove(); } });

  7. python-lambda用法

    前言: lambda函数也叫匿名函数,即,函数没有具体的名称. 一.基础 lambda语句构建的其实是一个函数对象.匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果 ...

  8. 第13章 TCP编程(1)_socket套接字

    1. socket套接字 (1)套接字简介 ①socket是一种通讯机制,它包含一整套的调用接口和数据结构的定义,它给应用进程提供了使用如TCP/UDP等网络协议进行网络通讯的手段. ②Linux中的 ...

  9. 最短路径之迪杰斯特拉(Dijkstra)算法

    对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd ...

  10. 移动性能测试 | 持续集成中的 Android 稳定性测试

    前言 谈到Android稳定测试,大多数会联想到使用monkey工具来做测试.google官方提供了monkey工具,可以很快速点击被应用,之前我有一篇帖子提到了monkey工具的使用,详见: htt ...