美文网首页我爱编程
Vue整合百度文件上传组件WebUploader

Vue整合百度文件上传组件WebUploader

作者: running_house | 来源:发表于2018-05-23 15:53 被阅读0次

第一步:引入第三方js和css

简单粗暴,直接在index.html文件中引入

    <!--js文件-->
    <script type="text/javascript" src="/static/js/jquery.min.js"></script>
    <script type="text/javascript" src="/static/js/webuploader.min.js"></script>
    <!--css文件-->
    <link rel="stylesheet" type="text/css" href="/static/css/webuploader.css">

注意:也可通过安装依赖的方式,引入jquery插件

npm install jquery --save

  import $ from 'jquery' 

第二步:基于webuploader封装Vue组件

封装好的组件uploader.vue如下,接口可以根据具体的业务进行扩展。
注意:功能和ui分离,此组建封装好了基本的功能,没有提供ui,ui在具体的页面上去实现。

<template>
    <div class="demo">
        <div id="uploader">
            <div class="queueList">
                <div id="dndArea" class="placeholder">
                    <div id="filePicker"></div>
                    <p>支持截图复制进来上传</p>
                </div>
            </div>
            <div class="statusBar" style="display:none;">
                <div class="progress">
                    <span class="text">0%</span>
                    <span class="percentage"></span>
                </div>
                <div class="info"></div>
                <div class="btns">
                    <div id="filePicker2"></div><div class="uploadBtn">开始上传</div>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
export default {
  data() {
    return {
      // 上传地址
      uploadUrl: process.env.BASE_API + '/File/UploadFile',
      $wrap: undefined,
      $queue: undefined,
      // 状态栏,包括进度和控制按钮
      $statusBar: undefined,
      // 文件总体选择信息。
      $info: undefined,
      // 上传按钮
      $upload: undefined,
      // 没选择文件之前的内容。
      $placeHolder: undefined,
      $progress: undefined,
      // 添加的文件数量
      fileCount: 0,
      // 添加的文件总大小
      fileSize: 0,
      // 优化retina, 在retina下这个值是2
      ratio: undefined,
      // 缩略图大小
      thumbnailWidth: undefined,
      thumbnailHeight: undefined,
      // 可能有pedding, ready, uploading, confirm, done.
      state: 'pedding',
      percentages: {},
      // 判断浏览器是否支持图片的base64
      isSupportBase64: undefined,
      // 检测是否已经安装flash,检测flash的版本
      flashVersion: undefined,
      supportTransition: undefined,
      uploader: undefined,
      fileList: undefined,
      fileData: {
        refId: undefined,
        projectId: undefined
      }
    }
  },
  mounted() {
    this.init()
    this.initWebUploader()
    this.fileData.refId = this.refId
    this.fileData.projectId = this.projectId
    this.clearFileList()
    this.getFileList()
  },
  props: {
    projectId: String,
    systemTime: Number,
    refId: String
  },
  methods: {
    init() {
      this.$wrap = $('#uploader')
      // 图片容器
      this.$queue = $('<ul class="filelist"></ul>').appendTo(this.$wrap.find('.queueList'))
      // 状态栏,包括进度和控制按钮
      this.$statusBar = this.$wrap.find('.statusBar')
      // 文件总体选择信息。
      this.$info = this.$statusBar.find('.info')
      // 上传按钮
      this.$upload = this.$wrap.find('.uploadBtn')
      // 没选择文件之前的内容。
      this.$placeHolder = this.$wrap.find('.placeholder')
      this.$progress = this.$statusBar.find('.progress').hide()
      // 添加的文件数量
      this.fileCount = 0
      // 添加的文件总大小
      this.fileSize = 0
      // 优化retina, 在retina下这个值是2
      this.ratio = window.devicePixelRatio || 1
      // 缩略图大小
      this.thumbnailWidth = 110 * this.ratio
      this.thumbnailHeight = 110 * this.ratio
      // 可能有pedding, ready, uploading, confirm, done.
      this.state = 'pedding'
      // 所有文件的进度信息,key为file id
      this.percentages = {}
      // // 判断浏览器是否支持图片的base64
      this.isSupportBase64 = (function() {
        var data = new Image()
        var support = true
        data.onload = data.onerror = function() {
          if (this.width != 1 || this.height != 1) {
            support = false
          }
        }
        data.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='
        return support
      })()
      // 检测是否已经安装flash,检测flash的版本
      this.flashVersion = (function() {
        var version

        try {
          version = navigator.plugins[ 'Shockwave Flash' ]
          version = version.description
        } catch (ex) {
          try {
            version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')
              .GetVariable('$version')
          } catch (ex2) {
            version = '0.0'
          }
        }
        version = version.match(/\d+/g)
        return parseFloat(version[ 0 ] + '.' + version[ 1 ], 10)
      })()
      this.supportTransition = (function() {
        var s = document.createElement('p').style,
          r = 'transition' in s ||
                            'WebkitTransition' in s ||
                            'MozTransition' in s ||
                            'msTransition' in s ||
                            'OTransition' in s
        s = null
        return r
      })()
    },
    // 初始化webuploader
    initWebUploader() {
      var that = this
      if (!WebUploader.Uploader.support('flash') && WebUploader.browser.ie) {
        // flash 安装了但是版本过低。
        if (that.flashVersion) {
          (function(container) {
            window['expressinstallcallback'] = function(state) {
              switch (state) {
                case 'Download.Cancelled':
                  alert('您取消了更新!')
                  break

                case 'Download.Failed':
                  alert('安装失败')
                  break

                default:
                  alert('安装已成功,请刷新!')
                  break
              }
              delete window['expressinstallcallback']
            }

            var swf = './expressInstall.swf'
            // insert flash object
            var html = '<object type="application/' +
                            'x-shockwave-flash" data="' + swf + '" '

            if (WebUploader.browser.ie) {
              html += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '
            }

            html += 'width="100%" height="100%" style="outline:0">' +
                            '<param name="movie" value="' + swf + '" />' +
                            '<param name="wmode" value="transparent" />' +
                            '<param name="allowscriptaccess" value="always" />' +
                            '</object>'

            container.html(html)
          })(that.$wrap)

          // 压根就没有安转。
        } else {
          that.$wrap.html('<a href="http://www.adobe.com/go/getflashplayer" target="_blank" border="0"><img alt="get flash player" src="http://www.adobe.com/macromedia/style_guide/images/160x41_Get_Flash_Player.jpg" /></a>')
        }

        return
      } else if (!WebUploader.Uploader.support()) {
        alert('Web Uploader 不支持您的浏览器!')
        return
      }

      // 实例化
      that.uploader = WebUploader.create({
        pick: {
          id: '#filePicker',
          label: '点击选择附件'
        },
        formData: {
          refId: undefined,
          projectId: undefined
        },
        dnd: '#dndArea',
        paste: '#uploader',
        swf: '../../../static/js/Uploader.swf',
        chunked: false,
        chunkSize: 512 * 1024,
        server: that.uploadUrl,
        // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
        disableGlobalDnd: true,
        fileNumLimit: 10,
        fileSizeLimit: 10 * 1024 * 1024, // 200 M
        fileSingleSizeLimit: 5 * 1024 * 1024 // 50 M
      })

      // 拖拽时不接受 js, txt 文件。
      that.uploader.on('dndAccept', function(items) {
        var denied = false
        const len = items.length
        var i = 0
        // 修改js类型
        var unAllowed = 'text/plain;application/javascript '
        for (; i < len; i++) {
          // 如果在列表里面
          if (~unAllowed.indexOf(items[ i ].type)) {
            denied = true
            break
          }
        }
        return !denied
      })

      // 文件发送前
      that.uploader.on('uploadBeforeSend', function(file, data) {
        data.refId = that.refId
        data.projectId = that.projectId
      })

      // 进度条
      that.uploader.on('uploadProgress', function(file, percentage) {
        var $li = $('#' + file.id)
        var $percent = $li.find('.progress span')

        $percent.css('width', percentage * 100 + '%')
        that.percentages[ file.id ][ 1 ] = percentage
        that.updateTotalProgress()
      })

      // 当文件被加入队列以后触发
      that.uploader.on('fileQueued', (file) => {
        that.fileCount++
        that.fileSize += file.size

        if (that.fileCount === 1) {
          that.$placeHolder.addClass('element-invisible')
          that.$statusBar.show()
        }

        that.addFile(file)
        that.setState('ready')
        that.updateTotalProgress()
      })

      // 当文件被移除队列后触发
      that.uploader.on('fileDequeued', (file) => {
        that.fileCount--
        that.fileSize -= file.size

        if (!that.fileCount) {
          that.setState('pedding')
        }

        that.removeFile(file)
        that.updateTotalProgress()
      })
      //文件上传完成后触发
      that.uploader.on('uploadFinished', function(type) {
        that.setState('confirm')
      })
      //文件开始上传时触发
      that.uploader.on('startUpload', function(type) {
        that.setState('uploading')
      })
      // 文件暂停上传时触发
      that.uploader.on('stopUpload', function(type) {
        that.setState('paused')
      })
      //文件上传出错后触发
      that.uploader.on('error', function(code) {
        var errMsg
        switch (code) {
          case 'F_EXCEED_SIZE':
            errMsg = '文件大小超出'
            break

          case 'interrupt':
            errMsg = '上传暂停'
            break

          default:
            errMsg = '上传失败,请重试'
            break
        }
        that.$message({
          message: errMsg,
          type: 'error'
        })
      })
      
      that.$upload.on('click', function() {
        if ($(that).hasClass('disabled')) {
          return false
        }
        if (that.state === 'ready') {
          that.uploader.upload()
        } else if (that.state === 'paused') {
          that.uploader.upload()
        } else if (that.state === 'uploading') {
          that.uploader.stop()
        }
      })
      that.$info.on('click', '.retry', function() {
        that.uploader.retry()
      })

      that.$info.on('click', '.ignore', function() {
        alert('todo')
      })

      that.$upload.addClass('state-' + that.state)
      that.updateTotalProgress()
    },
    addFile(file) {
      var that = this
      var $li = $('<li id="' + file.id + '">' +
                    '<p class="title">' + file.name + '</p>' +
                    '<p class="imgWrap"></p>' +
                    '<p class="progress"><span></span></p>' +
                    '</li>')
      var $btns = $('<div class="file-panel">' +
                            '<span class="cancel">删除</span></div>').appendTo($li)
      var $prgress = $li.find('p.progress span')
      var $wrap = $li.find('p.imgWrap')
      var $info = $('<p class="error"></p>')
      var showError = function(code) {
        switch (code) {
          case 'F_EXCEED_SIZE':
            text = '文件大小超出'
            break
          case 'interrupt':
            text = '上传暂停'
            break
          default:
            text = '上传失败,请重试'
            break
        }
        $info.text(text).appendTo($li)
      }

      if (file.getStatus() === 'invalid') {
        showError(file.statusText)
      } else {
      // @todo lazyload
        $wrap.text('预览中')
        that.uploader.makeThumb(file, function(error, src) {
          var img
          if (error) {
            $wrap.text('不能预览')
            return
          }
          // 判断浏览器是否支持图片的base64
          if (that.isSupportBase64) {
            img = $('<img src="' + src + '">')
            $wrap.empty().append(img)
          } else {
            // 预览操作,根据实际情况
            $.ajax('../preview.action', {
              method: 'POST',
              data: src,
              dataType: 'json'
            }).done(function(response) {
              if (response.result) {
                img = $('<img src="' + response.result + '">')
                $wrap.empty().append(img)
              } else {
                $wrap.text('预览出错')
              }
            })
          }
        }, that.thumbnailWidth, that.thumbnailHeight)

        that.percentages[ file.id ] = [file.size, 0]
        file.rotation = 0
      }

      file.on('statuschange', function(cur, prev) {
        if (prev === 'progress') {
          $prgress.hide().width(0)
        } else if (prev === 'queued') {
          $li.off('mouseenter mouseleave')
          $btns.remove()
        }
        // 成功
        if (cur === 'error' || cur === 'invalid') {
          showError(file.statusText)
          that.percentages[ file.id ][ 1 ] = 1
        } else if (cur === 'interrupt') {
          showError('interrupt')
        } else if (cur === 'queued') {
          that.percentages[ file.id ][ 1 ] = 0
        } else if (cur === 'progress') {
          $info.remove()
          $prgress.css('display', 'block')
        } else if (cur === 'complete') {
          $li.append('<span class="success"></span>')
        }

        $li.removeClass('state-' + prev).addClass('state-' + cur)
      })

      $li.on('mouseenter', function() {
        $btns.stop().animate({ height: 30 })
      })

      $li.on('mouseleave', function() {
        $btns.stop().animate({ height: 0 })
      })

      $li.on('click', function() {
        window.open(file.source.src)
      })

      $btns.on('click', 'span', function() {
        var index = $(this).index()
        var deg

        switch (index) {
          case 0:
            that.uploader.removeFile(file)
            return

          case 1:
            file.rotation += 90
            break

          case 2:
            file.rotation -= 90
            break
        }

        if (this.supportTransition) {
          deg = 'rotate(' + file.rotation + 'deg)'
          $wrap.css({
            '-webkit-transform': deg,
            '-mos-transform': deg,
            '-o-transform': deg,
            'transform': deg
          })
        } else {
          $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')')
        }
      })

      $li.appendTo(this.$queue)
    },
    removeFile(file) {
      var that = this
      var $li = $('#' + file.id)

      delete that.percentages[ file.id ]
      this.updateTotalProgress()
      $li.off().find('.file-panel').off().end().remove()
      if (file.source.id === undefined) {
        return
      }
      // 删除远程文件
      fileRemove(file.source.id).then(response => {
        if (response.data.success) {
          this.$message({
            message: '删除附件成功',
            type: 'success'
          })
        } else {
          this.$message({
            message: response.data.msg,
            type: 'error'
          })
        }
      })
    },
    updateTotalProgress() {
      var that = this
      var loaded = 0
      var total = 0
      var spans = this.$progress.children()
      var percent

      $.each(that.percentages, function(k, v) {
        total += v[ 0 ]
        loaded += v[ 0 ] * v[ 1 ]
      })

      percent = total ? loaded / total : 0

      spans.eq(0).text(Math.round(percent * 100) + '%')
      spans.eq(1).css('width', Math.round(percent * 100) + '%')
    },
    setState(val) {
      var that = this
      var stats

      if (val === that.state) {
        return
      }

      that.$upload.removeClass('state-' + that.state)
      that.$upload.addClass('state-' + val)
      that.state = val
      switch (that.state) {
        case 'pedding':
          that.$placeHolder.removeClass('element-invisible')
          that.$queue.show()
          that.$statusBar.addClass('element-invisible')
          that.uploader.refresh()
          break

        case 'ready':
          that.$placeHolder.addClass('element-invisible')
          $('#filePicker2').removeClass('element-invisible')
          that.$queue.show()
          that.$statusBar.removeClass('element-invisible')
          that.uploader.refresh()
          break

        case 'uploading':
          $('#filePicker2').addClass('element-invisible')
          that.$progress.show()
          that.$upload.text('暂停上传')
          break

        case 'paused':
          that.$progress.show()
          that.$upload.text('继续上传')
          break

        case 'confirm':
          that.$progress.hide()
          $('#filePicker2').removeClass('element-invisible')
          that.$upload.text('开始上传')

          stats = that.uploader.getStats()
          if (stats.successNum && !stats.uploadFailNum) {
            that.setState('finish')
            return
          }
          break
        case 'finish':
          stats = that.uploader.getStats()
          if (stats.successNum) {
            // alert('上传成功')
          } else {
          // 没有成功的图片,重设
            that.state = 'done'
            location.reload()
          }
          break
      }
    },
    // 清空文件列表
    clearFileList() {
      this.$info.empty()
      this.$queue.empty()
      this.fileCount = 0
      this.fileSize = 0
    },
    // 获取已上传的文件列表 
    getFileList() {
      this.fileList = []
      if (this.fileData.projectId !== undefined && this.fileData.refId !== undefined) {
        getFileList(this.fileData).then(response => {
          this.fileList = this.formatUrl(response.data)
        })
      }
    },
    // 将已上传的文件加载到组件列表中
    formatUrl(files) {
      for (let i = 0; i < files.length; i++) {
        files[i].url = process.env.BASE_API + files[i].url
        const obj = {}
        obj.name = files[i].name
        obj.size = files[i].size
        obj.lastModifiedDate = item.createTime
        obj.id = files[i].Id
        obj.src = files[i].url
        obj.ext = item.fileType.substr(1)

        var file = new WebUploader.File(obj)
        // 此处是关键,将文件状态改为'已上传完成'
        file.setStatus('complete')
        this.addFile(file)
      }
      return files
    }
  },
  watch: {
    systemTime() {
      this.fileData.refId = this.refId
      this.fileData.projectId = this.projectId
      this.clearFileList()
      this.getFileList()
    }
  }
}
</script>

第三步:组件引用

在vue项目中引入开发好的组件,需要三步

<!-- 1、引入组件 -->
import vueUploader from '@/components/common/uploader.vue'
<!-- 2、注册组件-->
components: { 
  vueUploader
},
 <!-- 3、使用组件 -->
 <vue-uploader :projectId='undefined' :refId='undefined' :systemTime="this.systemTime"></vue-uploader>

相关文章

网友评论

    本文标题:Vue整合百度文件上传组件WebUploader

    本文链接:https://www.haomeiwen.com/subject/xomrjftx.html