vue.js + axios.js图片压缩处理并上传到服务器demo

14 篇文章 0 订阅
4 篇文章 0 订阅

点击查看效果

图片压缩原理

将图片重新画入一个canvas中。可设置最大宽度,再按图片宽高比例定义canvas画布的宽高。

完整代码demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传图片</title>
    <meta name="renderer" content="webkit">
    <meta name="viewport"
          content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>

    <link rel="stylesheet" href="css/upload-img.css">
</head>
<body>
<div id="app" class="container" v-cloak>
    <div class="uploading-data" v-if="isUploading"></div>

    <div class="upload-img-column">
        <div class="words">上传图片 ({{imgTempList.length}}/5)</div>
        <div class="upload-wrap">
            <div class="box">
                <label class="p dotted">
                    <input type="file" accept="image/jpg,image/jpeg,image/png" name="file"
                           @change="onChooseImage($event)"/>
                    <img src="./img/jiahao.png" alt="">
                </label>
            </div>
            <template v-for="(imgItem, imgIndex) in imgTempList">
                <div class="box">
                    <div class="p">
                        <img :src="imgItem">
                        <div class="delete" @click.stop="deleteImg(imgIndex)">
                            <img src="./img/guanbi.png" alt="">
                        </div>
                    </div>
                </div>
            </template>
        </div>
    </div>

    <button class="l-btn" @click="onUploadImg">上传</button>

    <!-- 图片上传成功后返回的路径(没必要的) -->
    <div class="success-path">
        <template v-for="(item, index) in successPath">
            <a :href="item" target="_blank">{{item}}</a>
        </template>
    </div>

</div>

<script src="js/vue-2.5.21.js"></script>
<script src="js/axios.js"></script>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            imgTempList: [], //图片临时路径列表
            isUploading: false, //是否正在上传
            successPath: [], //上传成功后的路径(没必要)
        },
        mounted: function () {
            var that = this;
        },
        watch: {},
        methods: {
            //选择图片
            onChooseImage: function (event) {
                var that = this;

                //判断图片数量是否已上限
                var currentImgTempArray = that.imgTempList;
                if (currentImgTempArray.length >= 5) {
                    alert("最多上传5张图片");
                    return false;
                }

                //使用FileReader对文件对象进行操作
                var reader = new FileReader();
                reader.readAsDataURL(event.target.files[0]); //将读取到的文件编码成Data URL
                reader.onload = function () { //读取完成时
                    var replaceSrc = reader.result; //文件输出的内容


                    //调用图片压缩处理方法
                    that.compressedImage({
                        src: replaceSrc,
                        quality: 0.8,
                        success: function (src) {
                            //将压缩后的路径 追加到临时路径数组中
                            var totalList = [];
                            if (currentImgTempArray.length > 0) {
                                totalList = currentImgTempArray.concat(src);
                            } else {
                                totalList[0] = src;
                            }
                            that.imgTempList = totalList;
                        }
                    });
                };

            },

            //删除某张图片
            deleteImg: function (idx) {
                var that = this;
                that.imgTempList.splice(idx, 1);
            },


            //提交上传图片
            onUploadImg: function () {
                var that = this;
                var imgTempList = that.imgTempList;
                if (imgTempList.length > 0) {

                    that.isUploading = true; //正在上传 显示遮罩层 防止连续点击

                    var countNum = 0; //计算数量用的 判断上传到第几张图片了

                    //map循环遍历上传图片
                    imgTempList.map(function (imgItem, imgIndex) {
                        var files = that.dataURLtoFile(imgItem, 'pj' + Date.now() + '.jpg'); //DataURL转File

                        //创FormData对象
                        var formdata = new FormData();
                        //append(key,value)在数据末尾追加数据。 这儿的key值需要和后台定义保持一致
                        formdata.append('img', files);

                        //用axios上传,
                        axios({
                            method: "POST",
                            url: "http://www.clluo.com:8060/uploadImg",
                            data: formdata,
                            headers: {
                                "Content-Type": "multipart/form-data"
                            }
                        }).then(function (res) {
                            countNum++;
                            //图片全部上传完后去掉遮罩层
                            if (countNum >= imgTempList.length) {
                                that.isUploading = false;
                            }

                            //没必要的代码 👇
                            var list = [];
                            if (that.successPath.length > 0) {
                                list = that.successPath.concat(res.data.path);
                            } else {
                                list[0] = res.data.path;
                            }
                            that.successPath = list;

                        }).catch(function (error) {
                            console.error(error);
                        });
                    });
                }
            },

            /**
             * 压缩图片处理
             * @src 需要压缩的图片base64路径
             * @quality 图片质量 0-1,默认1
             * @success()  成功后的回调
             * */
            compressedImage: function (params) {
                var that = this;

                var initParams = {
                    src: params.src || "",
                    quality: params.quality || 1,
                };

                var image = new Image();
                image.src = initParams.src;
                image.onload = function () {
                    //获取图片初始宽高
                    var width = image.width;
                    var height = image.height;
                    //判断图片宽度,再按比例设置宽度和高度的值
                    if (width > 1024) {
                        width = 1024;
                        height = Math.ceil(1024 * (image.height / image.width));
                    }

                    //将图片重新画入canvas中
                    var canvas = document.getElementById("compressCanvas");
                    if(!canvas){ //创建一个canvas画布
                        var body = document.body;
                        canvas = document.createElement("canvas"); //创建canvas标签
                        canvas.id = "compressCanvas"; //给外层容器添加一个id
                        canvas.style.position = "fixed";
                        canvas.style.zIndex = "-1";
                        canvas.style.opacity = "0";
                        canvas.style.top = "-100%";
                        canvas.style.left = "-100%";
                        body.append(canvas);
                    }

                    var context = canvas.getContext("2d");
                    canvas.width = width;
                    canvas.height = height;
                    context.beginPath();
                    context.fillStyle = "#ffffff";
                    context.fillRect(0, 0, width, height);
                    context.fill();
                    context.closePath();
                    context.drawImage(image, 0, 0, width, height);
                    var replaceSrc = canvas.toDataURL("image/jpeg", initParams.quality); //canvas转DataURL(base64格式)

                    params.success && params.success(replaceSrc);
                };
            },

            /**
             * 将base64转换为文件
             * @dataUrl base64路径地址
             * @fileName 自定义文件名字
             * */
            dataURLtoFile: function (dataUrl, fileName) {
                var arr = dataUrl.split(','), mime = arr[0].match(/:(.*?);/)[1],
                    bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
                while (n--) {
                    u8arr[n] = bstr.charCodeAt(n);
                }
                return new File([u8arr], fileName, {type: mime});
            },
        }
    });
</script>
</body>
</html>

css代码

[v-cloak] {
	display: none;
}

* {
	margin: 0;
	padding: 0;
	list-style: none;
	box-sizing: border-box;
	-moz-box-sizing: border-box;
	-webkit-box-sizing: border-box;
	word-break: break-all;
	word-wrap: break-word;
}

.container {
	width: 100%;
	max-width: 600px;
	min-width: 320px;
	margin: 0 auto;
}

.container .l-btn {
	display: -webkit-box;
	display: -ms-flexbox;
	display: flex;
	width: 150px;
	height: 40px;
	color: #fff;
	background: #05AFAE;
	border: none;
	border-radius: 5px;
	-webkit-box-shadow: 1px 2px 3px rgba(0, 0, 0, .1);
	        box-shadow: 1px 2px 3px rgba(0, 0, 0, .1);
	margin: 50px auto;
	-webkit-box-orient: horizontal;
	-webkit-box-direction: normal;
	    -ms-flex-direction: row;
	        flex-direction: row;
	-webkit-box-align: center;
	    -ms-flex-align: center;
	        align-items: center;
	-webkit-box-pack: center;
	    -ms-flex-pack: center;
	        justify-content: center;
}

.container .l-btn:focus {
	outline: none;
}

.container .l-btn:active {
	-webkit-transition: .1s;
	-o-transition: .1s;
	transition: .1s;
	-webkit-transform: scale(.95);
	    -ms-transform: scale(.95);
	        transform: scale(.95);
}


/* 上传图片栏目 START */
.upload-img-column {
	width: 100%;
	padding: 10px;
}

.upload-img-column .words {
	font-size: 14px;
}

.upload-img-column .upload-wrap {
	width: 100%;
	display: -webkit-box;
	display: -ms-flexbox;
	display: flex;
	-webkit-box-orient: horizontal;
	-webkit-box-direction: normal;
	    -ms-flex-direction: row;
	        flex-direction: row;
	-ms-flex-wrap: wrap;
	    flex-wrap: wrap;
}

.upload-img-column .upload-wrap .box {
	width: 33.33%;
	padding: 10px 10px 0 0;
}

.upload-img-column .upload-wrap .box .p {
	width: 100%;
	height: 0;
	padding-bottom: 100%;
	border-radius: 5px;
	position: relative;
	overflow: hidden;
}

.upload-img-column .upload-wrap .box .p img {
	position: absolute;
	width: 100%;
	height: 100%;
	border-radius: 5px;
	overflow: hidden;
	left: 50%;
	top: 50%;
	-webkit-transform: translate(-50%, -50%);
	    -ms-transform: translate(-50%, -50%);
	        transform: translate(-50%, -50%);
}

.upload-img-column .upload-wrap .box .p .delete {
	width: 30px;
	height: 30px;
	text-align: center;
	border-radius: 50%;
	background: #e0e0e0;
	position: absolute;
	right: 0;
	top: 0;
	z-index: 2;
	display: -webkit-box;
	display: -ms-flexbox;
	display: flex;
	-webkit-box-orient: horizontal;
	-webkit-box-direction: normal;
	    -ms-flex-direction: row;
	        flex-direction: row;
	-webkit-box-align: center;
	    -ms-flex-align: center;
	        align-items: center;
	-webkit-box-pack: center;
	    -ms-flex-pack: center;
	        justify-content: center;
	opacity: 0.8;
}

.upload-img-column .upload-wrap .box .p .delete:active {
	-webkit-transform: scale(0.95);
	    -ms-transform: scale(0.95);
	        transform: scale(0.95);
}

.upload-img-column .upload-wrap .box .p .delete img {
	width: 14px;
	height: 14px;
}

.upload-img-column .upload-wrap .box .p.dotted {
	display: block;
	border: dotted 2px #999;
}

.upload-img-column .upload-wrap .box .p.dotted input {
	display: none;
}

.upload-img-column .upload-wrap .box .p.dotted img {
	width: 60%;
	height: auto;
	position: absolute;
	left: 50%;
	top: 50%;
	-webkit-transform: translate(-50%, -50%);
	    -ms-transform: translate(-50%, -50%);
	        transform: translate(-50%, -50%);
	opacity: .8;
}

/* 上传图片栏目 END */

.uploading-data {
	position: fixed;
	width: 100%;
	height: 100%;
	background: rgba(255, 255, 255, 0.3);
	left: 0;
	top: 0;
	z-index: 1000;
}

.success-path {
	width: 100%;
	padding: 0 10px;
}

.success-path a {
	display: block;
	margin-top: 6px;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值