• OSS上传文件 组件


    <template>
      <div>
        <form :class="uploadBtnClass" class="image-upload-form" v-show="!hasImage" method="post" enctype="multipart/form-data" action="">
          <input type="file" class="image-upload-form-input" :id="'upload_btn_' + formID" @change="change" title=" ">
          <slot></slot>
        </form>
        <div class="image-crop-wrap" ref="imgShape" v-show="hasImage" :id="'upload_crop_box_' + formID">
          <div v-if="crop">
            <div class="crop-cloth"></div>
            <div class="image-crop-content fade">
              <div class="image-crop-content-main">
                <div class="img-origin-div">
                  <img class="img-origin" :id="'img_origin_'+formID" alt="Picture"/>
                </div>
                <p class="txt">头像预览</p>
                <div class="img-preview-small-div" :class="previewClass" :id="'preview_'+formID">
                </div>
                <div style="clear:both"></div>
                <div class="docs-buttons image-crop-foot">
                  <span class="btn-grey quit" @click="cancel">{{cropBtn.cancel}}</span>
                  <span class="btn-red save" @click="handleImageCropped">
                    <a class="clip-down">{{cropBtn.ok}}</a>
                  </span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>
    <style lang="scss">
      @import "ossUpload.css";
    </style>
    <script>
      import $ from "jquery";
      import props from "./props";
      import {getOssUploadToken} from "@/service/getData";
      import cropper from 'cropper';
      import Promise from 'es6-promise';
      Promise.polyfill();
      export default {
        name: "",
        props: props,
        data() {
          return {
            hasImage: false,
            formID: (Math.random() * 10000 + "").split(".")[0],
            imageCropper: "", //cropper操作对象
            options: {
              aspectRatio: this.aspectRatio,
              dragCrop: false,
              viewMode: 1,
              zoomable: false,
              movable: false,
              zoomOnTouch: false,
              zoomOnWheel: false
            }
          };
        },
        watch: {},
        mounted() {
          $("body").append($(".image-crop-wrap"));
        },
        methods: {
          _dispatch(name, res) {
            this.$emit && this.$emit(name, res);
          },
          //初始化剪裁工具
          initCropper: function () {
            let that = this;
            let o = "#upload_crop_box_" + that.formID;
            that.imageCropper = $(o).find("#img_origin_" + that.formID);
            let $dataX = $(o).find("#dataX");
            let $dataY = $(o).find("#dataY");
            let $dataHeight = $(o).find("#dataHeight");
            let $dataWidth = $(o).find("#dataWidth");
            let $dataScaleX = $(o).find("#dataScaleX");
            let $dataScaleY = $(o).find("#dataScaleY");
            this.options.crop = function (e) {
              $dataX.val(Math.round(e.x));
              $dataY.val(Math.round(e.y));
              $dataHeight.val(Math.round(e.height));
              $dataWidth.val(Math.round(e.width));
              $dataScaleX.val(e.scaleX);
              $dataScaleY.val(e.scaleY);
            };
            this.options.preview = "#preview_" + that.formID;
    
            /*cropper*/
    //        this.imageCropper.cropper(this.options);
          },
          //选择了上传的文件
          change: function (e) {
            if (URL) {
              this.imageCropper = $("#img_origin_" + this.formID);
              let uploadedImageURL;
              let files = e.target.files;
              if (files && files.length) {
                let file = files[0];
                let fileExt = file.name.substring(file.name.lastIndexOf(".") + 1);
                const extensionsArr = this.extensions.split(",");
                if (extensionsArr.length > 1) {
                  var reg = new RegExp("^[" + extensionsArr.join("|") + "]+$", "i");
                  if (!reg.test(fileExt)) {
                    this._dispatch("promptTip", {type: "warning", info: "请上传图片文件"});
                    return;
                  } else {
                    if (this.crop) {
                      this.initCropper();
                      if (uploadedImageURL) {
                        URL.revokeObjectURL(uploadedImageURL);
                      }
                      uploadedImageURL = URL.createObjectURL(file);
                      this.imageCropper
                        .cropper("destroy")
                        .attr("src", uploadedImageURL)
                        .cropper(this.options);
                      this.hasImage = true;
                    } else {
                      this.getPolicyOfOSS(file);
                    }
                    document.querySelector("#upload_btn_" + this.formID).value = "";
                  }
                }
              }
            }
          },
          //取消上传
          cancel: function () {
            this.hasImage = false;
          },
          //处理剪裁的文件为Blob对象
          handleImageCropped: function () {
            let result = this.imageCropper.cropper("getCroppedCanvas");
            this.getPolicyOfOSS(
              this.convertBase64UrlToBlob(result.toDataURL("image/jpeg"))
            );
          },
          //将base64编码转换为Blob
          convertBase64UrlToBlob: function (urlData) {
            let bytes = window.atob(urlData.split(",")[1]); //去掉url的头,并转换为byte
            //处理异常,将ascii码小于0的转换为大于0
            let ab = new ArrayBuffer(bytes.length);
            let ia = new Uint8Array(ab);
            for (let i = 0; i < bytes.length; i++) {
              ia[i] = bytes.charCodeAt(i);
            }
            return new Blob([ab], {type: "image/jpeg", filename: "upload.jpg"});
          },
          //url转为base64编码
          convertImgToBase64: function (url, callback, outputFormat) {
            url+='?random='+Math.random();
            let canvas = document.createElement("CANVAS"),
              ctx = canvas.getContext("2d"),
              img = new Image();
            img.crossOrigin = "";
            // img.setAttribute("crossOrigin", "anonymous");
            img.onload = function () {
              canvas.height = img.height;
              canvas.width = img.width;
              ctx.drawImage(img, 0, 0);
              var dataURL = canvas.toDataURL(outputFormat || "image/png");
              callback.call(this, dataURL);
              canvas = null;
            };
            img.src = url;
          },
          //获取上传所需的TOKEN
          getPolicyOfOSS: function (blob,fn) {
            let that = this;
            let data = {
              type: this.type,
              fetchNum: this.fetchNum,
              data: this.bodyData
            };
            //获取OSS
            if(this.isTemp){
              $.ajax({
                type: "POST",
                url: that.url,
                headers: {
                  "Access-Token": that.accessToken,
                  "Content-Type": "application/json;charset=UTF-8"
                },
                data: JSON.stringify(data),
                success: function (res) {
                  if (res.code === 200) {
                    let obj = res.data.token;
                    let data = {
                      key: obj.dir,
                      policy: obj.policy,
                      OSSAccessKeyId: obj.accessid,
                      success_action_status: "200",
                      callback: obj.callback,
                      signature: obj.signature,
                      verify: obj.verify,
                      host: obj.host
                    };
                    that.uploadImageToOSS(data, blob,fn);
                  } else {
                  }
                }
              });
            }else{
              $.ajax({
                type: "GET",
                url: that.url,
                headers: {
                  "Access-Token": that.accessToken,
                  "Content-Type": "application/json;charset=UTF-8"
                },
                success: function (res) {
                  let obj = res;
                  let data = {
                    key: obj.dir,
                    policy: obj.policy,
                    OSSAccessKeyId: obj.accessid,
                    success_action_status: "200",
                    callback: obj.callback,
                    signature: obj.signature,
                    verify: obj.verify,
                    host: obj.host
                  };
                  that.uploadImageToOSS(data, blob,fn);
                }
              });
            }
          },
          //上传OSS协议
          uploadImageToOSS: function (option, blob = "",fn) {
            let that = this;
            return new Promise((resolve, reject) => {
              let formData = new FormData(document.forms[0]); //这里连带form里的其他参数也一起提交了,如果不需要提交其他参数可以直接FormData无参数的构造函数
              formData.append("key", option.key);
              formData.append("policy", option.policy);
              formData.append("OSSAccessKeyId", option.OSSAccessKeyId);
              formData.append("success_action_status", option.success_action_status);
              formData.append("Cache-Control", 'no-cache');
              if(option.callback) formData.append("callback", option.callback);
              if(option.verify) formData.append("x:verify", option.verify);
              formData.append("signature", option.signature);
              formData.append("file", blob); //append函数的第一个参数是后台获取数据的参数名,和html标签的input的name属性功能相同
              let xmlHttpReq = null;
              //IE浏览器使用ActiveX
              if (window.ActiveXObject) {
                xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
              } else if (window.XMLHttpRequest) {
                //其它浏览器使用window的子对象XMLHttpRequest
                xmlHttpReq = new XMLHttpRequest();
              }
              if (xmlHttpReq !== null) {
                //设置回调,当请求的状态发生变化时,就会被调用
                xmlHttpReq.onreadystatechange = () => {
                  //等待上传结果
                  if (xmlHttpReq.readyState == 1) {
                  }
                  // 上传成功,返回的文件名,设置到div的背景中
                  if (xmlHttpReq.readyState === 4 && xmlHttpReq.status === 200) {
                    let data = {};
                    try {
                      if (xmlHttpReq.statusText == "OK") {
                        if (xmlHttpReq.responseText) {
                          data = JSON.parse(xmlHttpReq.responseText);
                          that._dispatch("changeImage", data.data);
                        } else {
                          that._dispatch("changeImage", data.responseURL);
                        }
                        that.hasImage = false;
                        if (fn) fn(data.data);
                        resolve(data);
                      }
                    } catch (e) {
                      reject({code: 407, data: "数据类型出错"});
                      that._dispatch("promptTip", {
                        type: "warning",
                        info: "图片上传失败"
                      });
                    }
                  }
                };
                //设置请求(没有真正打开),true:表示异步
                xmlHttpReq.open("POST", option.host, true);
                //不要缓存
                //xmlHttpReq.setRequestHeader("If-Modified-Since", "0");
                //提交请求
                xmlHttpReq.send(formData);
                //清除掉,否则下一次选择同样的文件就进入不到onchange函数中了
              }
            });
          }
        }
      };
    </script>
    

      

    export default {
      url: {
        type: String
      },
      type: {
        type: String,
        default: 'USER_AVATAR'
      },
      extensions: {
        type: String,
        default: 'png,jpg,jpeg,gif,svg,webp'
      },
      crop: {
        type: Boolean,
        default: false
      },
      aspectRatio: {
        type: Number,
        default: 1
      },
      uploadBtnClass: {
        type: String,
        default: ""
      },
      previewClass: {
        type: String,
        default: "circle"
      },
      cropBtn: {
        type: Object,
        default: function () {
          return {
            ok: '保存',
            cancel: '取消',
          }
        }
      },
      isTemp:{
        type:Boolean,
        default:true
      },
      uid: {
        type: Number,
        default: 0
      },
      accessToken: {
        type: String,
        default: ""
      },
      fetchNum: {
        type: Number,
        default: 1
      },
      bodyData: {
        type: Object,
        default: function () {
          return {}
        }
    .crop-cloth{position: fixed;top:0;bottom: 0;left: 0;100%;height:100%;background:rgba(0,0,0,.7);z-index: 1000}
    .image-crop-content{position: fixed;left:50%;top:50%;margin-left: -400px;margin-top:-250px;transition: all 0.1s; 800px;height: 500px;z-index: 3000;background-color: #222226;padding:25px;box-shadow: 0 0 3px 1px rgba(0,0,0,.7);transition: all 0.1s;}
    .image-crop-content-main{padding: 10px;position: relative;}
    .image-crop-content-main .txt{color: #fff;position: absolute;top:8px;right:8px;display: inline-block;186px;text-align: center;font-size: 15.5px;line-height: 30px;}
    .img-origin-div{502px;height:372px;border: 1px solid #191919;}
    /*.img-origin-div .img-origin{100%;height:100%}*/
    /*.img-origin-div img{max-100%;max-height:100%}*/
    .img-origin-div img{max-502px;max-height:372px}
    .image-crop-foot>span{font-size: 19px;145px;height:40px;letter-spacing: 2px;margin:10px 18px 0 18px;border: 1px solid #121214;cursor: pointer;
      background-color:#2F2F34;font-weight: bold;line-height: 38px;vertical-align: top;
    }
    .image-crop-foot .quit{color: #ff5454;}
    .image-crop-foot .save{background-color: #ff5454;border-color: #ff5454;}
    .image-crop-foot .save a{color: #27272B!important;display:block;text-decoration: none;font-weight: bold;}
    .image-crop-foot span:hover{box-shadow:0 0 0 1px #313035 inset,0 0 0 2px #2B2A2F inset;border:1px solid #39383D;background: #2B2B30;}
    .image-crop-foot .save:hover a{color: #ff5454!important;}
    /*预览*/
    .img-preview-small-div{
       142px;
      height: 142px;
      position: absolute;
      top: 50px;
      right: 25px;
      border-radius: 50%;
      overflow: hidden;
      display: inline-block;
      vertical-align: middle;
    }
    .img-preview-small{
      top: 50px;
    }
    .img-preview-small.rect .img-preview{186px!important;height:45px!important;}
    .img-preview-small.circle{142px!important;height:142px!important;margin-right:24px;border-radius: 50% !important;}
    .img-preview-small.circle .img-preview{142px!important;height:142px!important;border-radius: 50% !important;}
    /*确认*/
    .docs-buttons{text-align: center;}
    /*截图界面弹出*/
    /*.image-crop-content.show{display: block;transition: all 0.1s;}*/
    
    .file-input-btn{position:absolute;top:0;left:0;overflow:hidden;100%;height:100%;font-size:0;cursor:pointer;opacity:0}
    .image-upload-form{100%;height:100%;position:relative}
    .image-upload-form input[type="file"]{ 100%;height: 100%;padding:0;margin:0;border:none;position:absolute;top:0;left:0;overflow:hidden;opacity:0;z-index:5000}
    
    /* cropper */
    .cropper-container {
      direction: ltr;
      font-size: 0;
      line-height: 0;
      position: relative;
      -ms-touch-action: none;
      touch-action: none;
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
    }
    
    .cropper-container img {/*Avoid margin top issue (Occur only when margin-top <= -height)
     */
      display: block;
      height: 100%;
      image-orientation: 0deg;
      max-height: none !important;
      max- none !important;
      min-height: 0 !important;
      min- 0 !important;
       100%;
    }
    
    .cropper-wrap-box,
    .cropper-canvas,
    .cropper-drag-box,
    .cropper-crop-box,
    .cropper-modal {
      bottom: 0;
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
    }
    
    .cropper-wrap-box,
    .cropper-canvas {
      overflow: hidden;
    }
    
    .cropper-drag-box {
      background-color: #fff;
      opacity: 0;
    }
    
    .cropper-modal {
      background-color: #000;
      opacity: .5;
    }
    
    .cropper-view-box {
      display: block;
      height: 100%;
      outline-color: rgba(51, 153, 255, 0.75);
      outline: 1px solid #39f;
      overflow: hidden;
       100%;
    }
    
    .cropper-dashed {
      border: 0 dashed #eee;
      display: block;
      opacity: .5;
      position: absolute;
    }
    
    .cropper-dashed.dashed-h {
      border-bottom- 1px;
      border-top- 1px;
      height: 33.33333%;
      left: 0;
      top: 33.33333%;
       100%;
    }
    
    .cropper-dashed.dashed-v {
      border-left- 1px;
      border-right- 1px;
      height: 100%;
      left: 33.33333%;
      top: 0;
       33.33333%;
    }
    
    .cropper-center {
      display: block;
      height: 0;
      left: 50%;
      opacity: .75;
      position: absolute;
      top: 50%;
       0;
    }
    
    .cropper-center:before,
    .cropper-center:after {
      background-color: #eee;
      content: ' ';
      display: block;
      position: absolute;
    }
    
    .cropper-center:before {
      height: 1px;
      left: -3px;
      top: 0;
       7px;
    }
    
    .cropper-center:after {
      height: 7px;
      left: 0;
      top: -3px;
       1px;
    }
    
    .cropper-face,
    .cropper-line,
    .cropper-point {
      display: block;
      height: 100%;
      opacity: .1;
      position: absolute;
       100%;
    }
    
    .cropper-face {
      background-color: #fff;
      left: 0;
      top: 0;
    }
    
    .cropper-line {
      background-color: #39f;
    }
    
    .cropper-line.line-e {
      cursor: e-resize;
      right: -3px;
      top: 0;
       5px;
    }
    
    .cropper-line.line-n {
      cursor: n-resize;
      height: 5px;
      left: 0;
      top: -3px;
    }
    
    .cropper-line.line-w {
      cursor: w-resize;
      left: -3px;
      top: 0;
       5px;
    }
    
    .cropper-line.line-s {
      bottom: -3px;
      cursor: s-resize;
      height: 5px;
      left: 0;
    }
    
    .cropper-point {
      background-color: #39f;
      height: 5px;
      opacity: .75;
       5px;
    }
    
    .cropper-point.point-e {
      cursor: e-resize;
      margin-top: -3px;
      right: -3px;
      top: 50%;
    }
    
    .cropper-point.point-n {
      cursor: n-resize;
      left: 50%;
      margin-left: -3px;
      top: -3px;
    }
    
    .cropper-point.point-w {
      cursor: w-resize;
      left: -3px;
      margin-top: -3px;
      top: 50%;
    }
    
    .cropper-point.point-s {
      bottom: -3px;
      cursor: s-resize;
      left: 50%;
      margin-left: -3px;
    }
    
    .cropper-point.point-ne {
      cursor: ne-resize;
      right: -3px;
      top: -3px;
    }
    
    .cropper-point.point-nw {
      cursor: nw-resize;
      left: -3px;
      top: -3px;
    }
    
    .cropper-point.point-sw {
      bottom: -3px;
      cursor: sw-resize;
      left: -3px;
    }
    
    .cropper-point.point-se {
      bottom: -3px;
      cursor: se-resize;
      height: 20px;
      opacity: 1;
      right: -3px;
       20px;
    }
    
    @media (min- 768px) {
      .cropper-point.point-se {
        height: 15px;
         15px;
      }
    }
    
    @media (min- 992px) {
      .cropper-point.point-se {
        height: 10px;
         10px;
      }
    }
    
    @media (min- 1200px) {
      .cropper-point.point-se {
        height: 5px;
        opacity: .75;
         5px;
      }
    }
    
    .cropper-point.point-se:before {
      background-color: #39f;
      bottom: -50%;
      content: ' ';
      display: block;
      height: 200%;
      opacity: 0;
      position: absolute;
      right: -50%;
       200%;
    }
    
    .cropper-invisible {
      opacity: 0;
    }
    
    .cropper-bg {
      background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
    }
    
    .cropper-hide {
      display: block;
      height: 0;
      position: absolute;
       0;
    }
    
    .cropper-hidden {
      display: none !important;
    }
    
    .cropper-move {
      cursor: move;
    }
    
    .cropper-crop {
      cursor: crosshair;
    }
    
    .cropper-disabled .cropper-drag-box,
    .cropper-disabled .cropper-face,
    .cropper-disabled .cropper-line,
    .cropper-disabled .cropper-point {
      cursor: not-allowed;
    }
    

      

    } }

      

  • 相关阅读:
    关于回调地狱
    node.js 关于跨域和传递给前台参数
    关于js的当前日期的格式化,和两个日期之间的相减的天数
    CSS 关于让页面的高度达到电脑屏幕的底部
    前端 为什么我选择用框架而不是Jquery
    关于webpack打包图片的路径问题
    关于webpack打包js和css
    微信小程序网络请求的setDate
    WinSocket聊天程序实例(多线程)
    Orcal的JDBC数据连接方式
  • 原文地址:https://www.cnblogs.com/lisiyang/p/8426057.html
Copyright © 2020-2023  润新知