js 实现图片上传预览效果(支持多张预览)

案例一:

1.效果图:

2.源码:

<!DOCTYPE html>
<html>
<head>
<title>HTML5上传图片预览</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="http://www.codefans.net/ajaxjs/jquery-1.6.2.min.js"></script>
<style>
  #imgList{
    list-style:none;
    overflow:hidden;
    clear:both;
  }
  #imgList li{
    float:left;
    width:120px;height:120px;margin:10px 10px 0 0;
    overflow:hidden;
    border-radius:4px;
    background-color:pink;
  }
  #imgList li img{
    width:100%;
  }
  .input-file-box{
    display: inline-block;
    position: relative;
    padding: 3px 5px;
    overflow: hidden;
    color:#fff;
    background-color: #ccc;
  }
  .file-input{
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
      left: 0;
      outline: none;
      background-color: transparent;
      filter:alpha(opacity=0);
    -moz-opacity:0;
    -khtml-opacity: 0;
    opacity: 0;
  }
</style>
</head>
<body>
<h3>请选择图片文件:JPG/GIF</h3>
<form name="form0" id="form0" >
  <!-- 这里特别说一下这个 multiple="multiple" 添加上这个之后可以一次选择多个文件进行上传,是 html5 的新属性-->
  <!-- <input type="file" name="file0" id="file0" multiple="multiple" /><br> -->
  <div class="input-file-box">
    <input type="file" class="file-input"  id="file0" multiple="multiple" />
    上传文件
  </div>
  <ul id="imgList">
    <li><img src="" alt=""></li>
    <li><img src="" alt=""></li>
  </ul>
</form>
<script>  
$("#file0").change(function(){
  // this.files[0]代表的是选择的文件资源的第一个,因为上面写了 multiple="multiple" 就表示上传文件可能不止一个
  console.log(this.files)
  var arr = [];
  for(var val of this.files){
    var imgUrl = getObjectURL(val) ;
    if (imgUrl) {
      // 在这里修改图片的地址属性
      arr.push('<li><img src="'+imgUrl+'"/></li>')
    }
    $('#imgList').html(arr.join(''))
  }
}) ;
//建立一個可存取到該file的url
function getObjectURL(file) {
  var url = null ; 
  // 下面函数执行的效果是一样的,只是需要针对不同的浏览器执行不同的 js 函数而已
  if (window.createObjectURL!=undefined) { // basic
    url = window.createObjectURL(file) ;
  } else if (window.URL!=undefined) { // mozilla(firefox)
    url = window.URL.createObjectURL(file) ;
  } else if (window.webkitURL!=undefined) { // webkit or chrome
    url = window.webkitURL.createObjectURL(file) ;
  }
  return url ;
}
</script>
</body>
</html>

案例二、

模仿 element-ui 的 el-upload 上传组件实现

功能:

1.支持预览

2.返回二进制格式

upload.vue源码:

<!-- 自定义上传图片组件 -->
<template>
  <div v-show="preViewUrl" class="upload-wrap flex">
    <img class="img-box box-w" :src="preViewUrl" alt="">
    <div class="upload-box box-w">
      <svg-icon class="icon icon-qr-code" icon-class="icon-qr-code" />
      <div class="upload-text">点击上传</div>
      <input type="file" class="file-input" :multiple="isMultiple" @change="fileChange">
    </div>
  </div>
</template>

<script>
export default {
  name: 'UploadImg',
  props: {
    imageUrl: {
      type: String,
      default: ''
    },
    isMultiple: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      preViewUrl: '',
      imgsUrl: '',
      mime: ''
    }
  },
  watch: {
    imageUrl: {
      handler() {
        this.preViewUrl = this.imageUrl
      },
      immediate: true
    },
    imgsUrl(val) {
      this.preViewUrl = val
    }
  },
  methods: {
    /**
     * database64文件格式转换为2进制
     * @param  {[String]} data dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
     * @param  {[String]} mime [description]
     * @return {[blob]}      [description]
     */
    data2blob(data, mime) {
      data = data.split(',')[1]
      data = window.atob(data)
      var ia = new Uint8Array(data.length)
      for (var i = 0; i < data.length; i++) {
        ia[i] = data.charCodeAt(i)
      }
      // canvas.toDataURL 返回的默认格式就是 image/png
      return new Blob([ia], {
        type: mime
      })
    },
    /**
     * input chanage 触发事件
     */
    fileChange(e) {
      const files = e.target.files || e.dataTransfer.files
      this.setSourceImg(files[0]).then(() => {
        const fileBlob = this.data2blob(this.imgsUrl, this.mime)
        const turnData = {
          imgUrl: this.imgsUrl,
          file: fileBlob
        }
        this.$emit('updateImgData', turnData)
      })
    },
    /**
     * 二进制流的生成
     */
    setSourceImg(file) {
      const that = this
      return new Promise((resolve, reject) => {
        const fr = new FileReader()
        fr.onload = function(e) {
          that.imgsUrl = fr.result
          that.mime = file.type
          resolve(fr.result)
        }
        fr.onerror = function() {
          reject()
        }
        fr.readAsDataURL(file)
      })
    }
  }
}
</script>

<style lang="scss" scoped>
  @import "~@/styles/variables.scss"; // css变量
  .upload-wrap{
    justify-content: flex-start;
    .box-w{
      width:200px;
      height:150px;
    }
    .upload-box{
      position:relative;
      margin-left:10px;
      overflow:hidden;
      text-align:center;
      cursor:pointer;
      border:1px dashed #e0e0e0;
      border-radius: 6px;
      transition: border .3s;

      &:hover{
        border-color:$mainColor;
      }
    }
    .upload-text{
      margin-top:-10px;
      line-height: 20px;
      font-size: 14px;
      color: #606266;
    }
    .icon-qr-code {
      $wh: 110px;
      width: $wh;
      height: $wh;
      transition: border .3s;
    }
    .file-input{
      position: absolute;
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      outline: none;
      background-color: transparent;
      filter:alpha(opacity=0);
      -moz-opacity:0;
      -khtml-opacity: 0;
      opacity: 0;
    }

    .img-box{
        overflow:hidden;
        border-radius:4px;
        background-color:pink;
    }
  }

</style>

调用:

<UploadImg :image-url="imageUrl" @updateImgData="updateImgData" />

案例三、

来源与网络

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>XMLHttpRequest上传文件</title>
    <script type="text/javascript">
        /*
        三个参数
        file:一个是文件(类型是图片格式),
        w:一个是文件压缩的后宽度,宽度越小,字节越小
        objDiv:一个是容器或者回调函数
        photoCompress()
         */
        function photoCompress(file, w, objDiv) {
            debugger
            var ready = new FileReader();
            /*开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/
            ready.readAsDataURL(file);
            ready.onload = function () {
                var re = this.result;
                canvasDataURL(re, w, objDiv)
            }
        }

        function canvasDataURL(path, obj, callback) {
            debugger
            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) {
                    // debugger
              const arr = urlData.split(',')
              const mime = arr[0].match(/:(.*?);/)[1]
              const bstr = atob(arr[1])
              let n = bstr.length
              const u8arr = new Uint8Array(n)
              while (n--) {
                u8arr[n] = bstr.charCodeAt(n)
              }
              const val = new Blob([u8arr], { type: mime })
              // debugger
              return val
        }


        var xhr;
        //上传文件方法
        function UpladFile() {
            var fileObj = document.getElementById("file").files[0]; // js 获取文件对象
            var url = "后台图片上传接口"; // 接收上传文件的后台地址 

            var form = new FormData(); // FormData 对象

            if (fileObj.size / 1024 > 1025) { //大于1M,进行压缩上传
                console.log('大于1M,进行压缩上传')
                debugger
                photoCompress(fileObj, {
                    quality: 0.2
                }, function (base64Codes) {
                    //console.log("压缩后:" + base.length / 1024 + " " + base);
                    var bl = convertBase64UrlToBlob(base64Codes);
                    form.append("file", bl, "file_" + Date.parse(new Date()) + ".jpg"); // 文件对象
                    xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
                    xhr.open("post", url, true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理。
                    xhr.onload = uploadComplete; //请求完成
                    xhr.onerror = uploadFailed; //请求失败

                    xhr.upload.onprogress = progressFunction;//【上传进度调用方法实现】
                    xhr.upload.onloadstart = function () {//上传开始执行方法
                        ot = new Date().getTime();   //设置上传开始时间
                        oloaded = 0;//设置上传开始时,以上传的文件大小为0
                    };

                    xhr.send(form); //开始上传,发送form数据
                });
            } else { //小于等于1M 原图上传
                console.log('小于等于1M 原图上传');

                debugger
                form.append("file", fileObj); // 文件对象
                xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
                xhr.open("post", url, true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理。
                xhr.onload = uploadComplete; //请求完成
                xhr.onerror = uploadFailed; //请求失败

                xhr.upload.onprogress = progressFunction;//【上传进度调用方法实现】
                xhr.upload.onloadstart = function () {//上传开始执行方法
                    ot = new Date().getTime();   //设置上传开始时间
                    oloaded = 0;//设置上传开始时,以上传的文件大小为0
                };

                xhr.send(form); //开始上传,发送form数据
            }
        }

        //上传成功响应
        function uploadComplete(evt) {
            //服务断接收完文件返回的结果

            var data = JSON.parse(evt.target.responseText);
            if (data.success) {
                alert("上传成功!");
            } else {
                alert("上传失败!");
            }

        }
        //上传失败
        function uploadFailed(evt) {
            alert("上传失败!");
        }
        //取消上传
        function cancleUploadFile() {
            xhr.abort();
        }

        //上传进度实现方法,上传过程中会频繁调用该方法
        function progressFunction(evt) {
            var progressBar = document.getElementById("progressBar");
            var percentageDiv = document.getElementById("percentage");
            // event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0
            if (evt.lengthComputable) {//
                progressBar.max = evt.total;
                progressBar.value = evt.loaded;
                percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
            }
            var time = document.getElementById("time");
            var nt = new Date().getTime();//获取当前时间
            var pertime = (nt - ot) / 1000; //计算出上次调用该方法时到现在的时间差,单位为s
            ot = new Date().getTime(); //重新赋值时间,用于下次计算
            var perload = evt.loaded - oloaded; //计算该分段上传的文件大小,单位b
            oloaded = evt.loaded;//重新赋值已上传文件大小,用以下次计算
            //上传速度计算
            var speed = perload / pertime;//单位b/s
            var bspeed = speed;
            var units = 'b/s';//单位名称
            if (speed / 1024 > 1) {
                speed = speed / 1024;
                units = 'k/s';
            }
            if (speed / 1024 > 1) {
                speed = speed / 1024;
                units = 'M/s';
            }
            speed = speed.toFixed(1);
            //剩余时间
            var resttime = ((evt.total - evt.loaded) / bspeed).toFixed(1);
            time.innerHTML = ',速度:' + speed + units + ',剩余时间:' + resttime + 's';
            if (bspeed == 0) time.innerHTML = '上传已取消';
        }
    </script>
</head>

<body>
    <progress id="progressBar" value="0" max="100" style="width: 300px;"></progress>
    <span id="percentage"></span><span id="time"></span>
    <br /><br />
    <input type="file" id="file" name="myfile" accept="image/x-png, image/jpg, image/jpeg, image/gif" />
    <input type="button" onclick="UpladFile()" value="上传" />
    <input type="button" onclick="cancleUploadFile()" value="取消" />
</body>

</html>

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kaiking_g

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值