1. 程式人生 > >vue上傳(相容IE9)

vue上傳(相容IE9)

專案中vue檔案上傳功能原來使用的是element ui元件,頭像上傳裁剪使用的是vue-image-crop-upload,但是這兩個元件只支援到IE10+,現在專案要求相容IE9,這兩個元件就沒辦法實現。

 我基於Web Uploader封裝了vue上傳功能,Web Uploader是一個簡單的以HTML5為主,FLASH為輔的上傳元件,IE10以下可以使用FLASH上傳。廢話不多說,直接上碼。

我將檔案放在components下:

其中index.vue為封裝的一層,Uploader.swf和webuploader.js可以在webupload官網下載

index.vue:

<template>
    <div class="_upload">
    </div>
</template>


<script>
  import 'jquery';
  import './webuploader';
  import swgimg from './Uploader.swf';

  export default {
    props: {
      // 上傳按鈕ID
      upload_button: {
        type: String,
        default: '._upload'
      },
      // 上傳地址
      cdnUrl: {
        type: String,
        default: ''
      },
      // 上傳最大數量 預設為100
      fileNumLimit: {
        type: Number,
        default: 100
      },
      // 大小限制 預設2M
      fileSingleSizeLimit: {
        type: Number,
        default: 2048000
      },
      //上傳token等引數
      formData: {
        type: Object,
        default: null
      },
      imageUrl: {
        type: String,
        default: ''
      },
      accept: {
        type: Object,
        default: null
      },
      keyGenerator: {
        type: Function,
        default: function (file) {
          const currentTime = new Date().getTime();
          const key = currentTime + "." + file.name;
          return key;
        }
      }
    },
    data() {
      return {
      };
    },
    mounted() {
      this.initWebUpload();
    },
    methods: {
      initWebUpload() {
        var self = this;
        var uploader = WebUploader.create({
          auto: true, // 選完檔案後,是否自動上傳
          swf: swgimg, // swf檔案路徑
          server: self.cdnUrl,  // 檔案接收服務端
          pick: {
            id: self.upload_button,
            multiple:false,
            label: ''
          }, // 選擇檔案的按鈕。可選

          // 允許選擇檔案格式。
          accept: self.accept,
          thread: 1,
          fileNumLimit: self.fileNumLimit, //限制上傳個數
          fileSingleSizeLimit: self.fileSingleSizeLimit, //限制單個上傳圖片的大小
          formData: self.formData,  //上傳七牛所需引數
          duplicate: true  //重複上傳
        });
        // 當有檔案被新增進佇列的時候,新增到頁面預覽
        uploader.on( 'fileQueued', function( file ) {
          uploader.options.formData.key = self.keyGenerator(file);
          self.$emit('before', file);
        });
        // 檔案上傳過程中建立進度條實時顯示。
        uploader.on( 'uploadProgress', function( file, percentage ) {
          self.$emit('progress', file, percentage);
        });
        uploader.on( 'uploadSuccess', function( file, response ) {
          self.$emit('success', file, response);
        });

        uploader.on( 'error', function( type ) {
          let errorMessage = '';
          if (type == "F_EXCEED_SIZE") {
            errorMessage = "檔案大小不能超過" + self.fileSingleSizeLimit/(1024*1000) + "M";
          } else if (type == "Q_EXCEED_NUM_LIMIT") {
            errorMessage = '檔案上傳已達到最大上限數';
          } else {
            errorMessage = "上傳出錯!請檢查後重新上傳!錯誤程式碼" + type;
          }
          self.$emit('error', errorMessage);
        });

        uploader.on( 'uploadComplete', function( file, response ) {
          self.$emit('complete', file, response);
        });

      },
    }
  }
</script>

<style>
  .webuploader-container {
    position: relative;
  }
  .webuploader-element-invisible {
    position: absolute !important;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
    clip: rect(1px,1px,1px,1px);
  }
  .webuploader-pick {
    position: relative;
    display: inline-block;
    cursor: pointer;
    background: #00b7ee;
    padding: 10px 15px;
    color: #fff;
    text-align: center;
    border-radius: 3px;
    overflow: hidden;
  }
  .webuploader-pick-hover {
    background: #00a2d4;
  }

  .webuploader-pick-disable {
    opacity: 0.6;
    pointer-events:none;
  }
</style>

這裡我說下我踩得幾個坑:

1. webuploader官網下載之後是存在css的,我使用

<style scoped>
    @import "./webuploader.css";
</style>
  但是未生效,我就將css樣式放入vue頁面中;

2.使用webuploader必須先引進jquery,不然會報 jQuery or Zepto not found! 錯誤;

3.import swf檔案時,必須在webpack.conf.js中新增

{
        //視訊載入
        test: /\.(mp4|flv|swf)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: "file-loader",
        options: {
          name: utils.assetsPath("video/[name].[hash:7].[ext]")
        }
不然會因為不識別這種格式報錯;

4.我使用webuploader的版本為0.1.5,webuploader.js中

 input.on( 'change', function( e ) {
                    var fn = arguments.callee,
                        clone;
    
                    me.files = e.target.files;
    
                    // reset input
                    clone = this.cloneNode( true );
                    clone.value = null;
                    this.parentNode.replaceChild( clone, this );
    
                    input.off();
                    input = $( clone ).on( 'change', fn )
                            .on( 'mouseenter mouseleave', mouseHandler );
    
                    owner.trigger('change');
                });
    
                label.on( 'mouseenter mouseleave', mouseHandler );
存在callee方法,如果在嚴格模式下,會報

Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

解決辦法為:修改該段程式碼
       var changeFn = (function even(that, e){

          var clone;

          me.files = e.target.files;

          // reset input
          clone = that.cloneNode( true );
          clone.value = null;
          that.parentNode.replaceChild( clone, that );

          input.off();
          input = $(clone).on('change', function(e){
            even(this, e);
          }).on('mouseenter mouseleave', mouseHandler);

          owner.trigger('change');
        });

        input.on('change', function(e){
          changeFn(this, e);
        });

        label.on( 'mouseenter mouseleave', mouseHandler );
   即可。

下面是呼叫實現功能的一個demo頁面

demo.vue:

<template>
  <div>
    <web-upload :cdn-url="cdnUrl" :form-data="cdnParams" @before="beforeUpload" :accept="accept"
                @progress="uploadProgress" @success="handleSuccess" :key-generator="keyGenerator"
                @error="error" @complete="handleComplete" upload_button=".btns">
    </web-upload>
    <p>
      <img v-if="imageUrl" :src="imageUrl" class="avatar">
      <i v-else class="el-icon-plus avatar-uploader-icon"></i>
    </p>
    <div class="progressContainer" :style="{display: display}">
      <div class="progress" :style="{width:progress+'%'}">
        <b>{{progress}}%</b>
      </div>
    </div>
    <div class="btns">
      <div id="picker">選擇檔案</div>
    </div>


  </div>
</template>

<style>
  .avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }

  .avatar-uploader .el-upload:hover {
    border-color: #20a0ff;
  }

  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
  }

  .avatar {
    width: 178px;
    height: 178px;
    display: block;
  }
</style>

<script>
  import WebUpload from 'components/webupload';

  export default {
    components: {
      WebUpload
    },
    data() {
      return {
        display: "none",
        progress: 0,
        accept: null,
        cdnUrl: '',
        host: '',
        imageUrl: '',
        cdnParams: {
          token: '',
          key: '',
          name: '',
          chunk: 0,
          chunks: 1
        }
      };
    },
    methods: {
      handleSuccess(file, res) {
        this.imageUrl = this.host.concat(res.key);
      },
      beforeUpload(file) {

      },
      uploadProgress(file, percentage) {
        this.display = "block";
        this.progress = percentage * 100;
      },
      error(message) {
        this.$message.error(message);
      },
      handleComplete() {
        this.display = "none";
      },
      keyGenerator(file) {
        const currentTime = new Date().getTime();
        this.cdnParams.key = "test/cdn/ie9/" + currentTime + "." + file.name;
        return this.cdnParams.key;
      }
    }
  }
</script>

我這是直接上傳到七牛CDN。

如有其他問題,可在評論留言

下面是呼叫API:


外掛已上傳NPM

注意:ie9使用的為flash,地址不支援https,所以伺服器地址使用http

r如有問題一的個簡單的以HTML5為主,FLASH為輔的現代檔案上傳元件一個簡單的以HTML5為主,FLASH為輔的現代檔案上傳元件一個簡單的以HTML5為主,FLASH為輔的現代檔案上傳元件一個簡單的以HTML5為主,FLASH為輔的現代檔案上傳元件