上传视频插件 WebUploader 从小白到专家

背景

由于我司业务关系,需实现兼容IE8+浏览器的视频上传功能,且支持多选断点上传。故借助Baidu WebFE(FEX)团队开发的webuploader文件上传插件实现此业务功能。

一、引用

文件上传引用分为2种

(1)、script 引用 http://cdn.staticfile.org/webuploader/0.1.0/webuploader.js

(2)、npm 引用 npm install WebUploader

二、控件初始化配置

let uploaderOptions = {
   //设置为 true 后,不需要手动调用上传,有文件选择即开始上传。[默认值:false] [可选] 
   auto: true,
   //flash 上传控件地址
   swf:'//static1.bitautoimg.com/web-component/yiche-upload-pc/js/Uploader.swf',
   // // 上传服务器地址
   server: "视频上传服务器地址",
   //上传是添加自定义参数
   formData: {},
   //是否已二进制的流的方式发送文件,这样整个上传内容
   sendAsBinary: false,
   //自定义请求头
   headers:{},
   // 超时时间
   timeout: 360000,
   //{int} [可选] [默认值:undefined] 验证文件总数量, 超出则不允许加入队列。
   fileNumLimit: 10,
   //[可选] [默认值:undefined] 指定Drag And Drop拖拽的容器,如果不指定,则不启动。
   dnd: '',
   //[可选] [默认值:false] 是否禁掉整个页面的拖拽功能,如果不禁用,图片拖进来的时候会默认被浏览器打开。
   disableGlobalDnd: false,
   //[可选] [默认值:undefined] 指定监听paste事件的容器,如果不指定,不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为document.body.
   paste: document.body,
   // 如果要分片,分多大一片? 默认大小为5M. 
   chunkSize: 1 * 1024 * 1024,
   // 验证单个文件大小是否超出限制, 超出则不允许加入队列 默认: 2M
   fileSingleSizeLimit: 2 * 1024 * 1024,
   //是否要分片处理大文件上传。
   chunked: true,
   //[默认值:POST] 文件上传方式,POST 或者 GET。
   method:'POST',
   accept: {
        title: 'videos',
        //图片后缀
        extensions: "mp4","rmvb","avi","flv","mov",
        //匹配格式
        mimeTypes: 'video/*'
   },
   //[可选] [默认值:undefined] 去重, 根据文件名字、文件大小和最后修改时间来生成hash Key
   duplicate:true,
   //不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
   resize: false,
   //[可选] [默认值:false] 是否允许在文件传输时提前把下一个文件准备好。 对于一个文件的准备工作比较耗时,比如图片压缩,md5序列化。 如果能提前在当前文件传输期处理,可以节省总体耗时。
   prepareNextFile: true,
   //上传线程并发数为 3
   threads: 3,
   //设置文件上传域的name
   fileVal:''  
}

let uploader = new WebUploader.Uploader(uploaderOptions)

初始化参数说明

属性名称说明
dnd{Selector} [可选] [默认值:undefined] 

指定Drag And Drop拖拽的容器,如果不指定,则不启动。

disableGlobalDnd{Selector} [可选] [默认值:false] 

是否禁掉整个页面的拖拽功能,如果不禁用,图片拖进来的时候会默认被浏览器打开。

paste{Selector} [可选] [默认值:undefined] 

指定监听paste事件的容器,如果不指定,不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为document.body.

pick {Selector, Object} [可选] [默认值:undefined] 

指定选择文件的按钮容器,不指定则不创建按钮。

  • id {Seletor|dom} 指定选择文件的按钮容器,不指定则不创建按钮。注意 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。
  • label {String} 请采用 innerHTML 代替
  • innerHTML {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。
  • multiple {Boolean} 是否开起同时选择多个文件能力。
accept {Array} [可选] [默认值:null] 

指定接受哪些类型的文件。 由于目前还有ext转mimeType表,所以这里需要分开指定。

  • title {String} 文字描述
  • extensions {String} 允许的文件后缀,不带点,多个用逗号分割。
  • mimeTypes {String} 多个用逗号分割。
  • {
        title: 'Images',
        extensions: 'gif,jpg,jpeg,bmp,png',
        mimeTypes: 'image/*'
    }
thumb

{Object} [可选] 配置生成缩略图的选项。

默认为:

{
    width: 110,
    height: 110,

    // 图片质量,只有type为`image/jpeg`的时候才有效。
    quality: 70,

    // 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false.
    allowMagnify: true,

    // 是否允许裁剪。
    crop: true,

    // 为空的话则保留原有图片格式。
    // 否则强制转换成指定的类型。
    type: 'image/jpeg'
}

compress{Object} [可选] 

配置压缩的图片的选项。如果此选项为false, 则图片在上传前不进行压缩。

{
    width: 1600,
    height: 1600,

    // 图片质量,只有type为`image/jpeg`的时候才有效。
    quality: 90,

    // 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false.
    allowMagnify: false,

    // 是否允许裁剪。
    crop: false,

    // 是否保留头部meta信息。
    preserveHeaders: true,

    // 如果发现压缩后文件大小比原来还大,则使用原来图片
    // 此属性可能会影响图片自动纠正功能
    noCompressIfLarger: false,

    // 单位字节,如果图片大小小于此值,不会采用压缩。
    compressSize: 0
}
auto{Boolean} [可选] [默认值:false] 

设置为 true 后,不需要手动调用上传,有文件选择即开始上传。

runtimeOrder{Object} [可选] [默认值:html5,flash] 

指定运行时启动顺序。默认会先尝试 html5 是否支持,如果支持则使用 html5, 否则使用 flash. 可以将此值设置成 flash,来强制使用 flash 运行时。

prepareNextFile{Boolean} [可选] [默认值:false] 

是否允许在文件传输时提前把下一个文件准备好。 某些文件的准备工作比较耗时,比如图片压缩,md5序列化。 如果能提前在当前文件传输期处理,可以节省总体耗时。

chunked{Boolean} [可选] [默认值:false]  是否要分片处理大文件上传。
chunkSize{Boolean} [可选] [默认值:5242880]  如果要分片,分多大一片? 默认大小为5M.
chunkRetry{Boolean} [可选] [默认值:2]  如果某个分片由于网络问题出错,允许自动重传多少次?
chunkRetryDelay{Number} [可选] [默认值:1000] 

开启重试后,设置重试延时时间, 单位毫秒。默认1000毫秒,即1秒.

threads{Boolean} [可选] [默认值:3]  上传并发数。允许同时最大上传进程数。
formData{Object} [可选] [默认值:{}]  文件上传请求的参数表,每次发送都会发送此对象中的参数。
fileVal{Object} [可选] [默认值:'file']  设置文件上传域的name。
method{Object} [可选] [默认值:POST]  文件上传方式,POST 或者 GET
sendAsBinary {Object} [可选] [默认值:false] 

是否已二进制的流的方式发送文件,这样整个上传内容php://input都为文件内容, 其他参数在$_GET数组中。

fileNumLimit{int} [可选] [默认值:undefined] 验证文件总数量, 超出则不允许加入队列。
fileSizeLimit{int} [可选] [默认值:undefined] 验证文件总大小是否超出限制, 超出则不允许加入队列。
fileSingleSizeLimit{int} [可选] [默认值:undefined] 验证单个文件大小是否超出限制, 超出则不允许加入队列。
duplicate{Boolean} [可选] [默认值:undefined] 

去重, 根据文件名字、文件大小和最后修改时间来生成hash Key.

disableWidgets {String, Array} [可选] [默认值:undefined] 

默认所有 Uploader.register 了的 widget 都会被加载,如果禁用某一部分,请通过此 option 指定黑名单。

三、初始化完配置就要添加文件了

//添加上传队列
uploader.addFiles(videoList)

四、监听上传文件事件

(1)在上传文件前,创建上传文件唯一值

//当文件被加入队列之前触发,此事件的handler返回值为false,则此文件不会被添加进入队列
uploader.on('beforeFileQueued',function(file){
    //创建唯一的文件GUID标识
    file.guid = createGuid()
    return true
})

 (2) 在上传文件前,组装分片配置

//每次上传前,如果分块传输,则带上分块信息参数
uploader.on('uploadBeforeSend',function(block, data, headers) {
        var deferred = WebUploader.Deferred();
        //删除无用默认属性
        delete data.id
        delete data.name
        delete data.type
        delete data.lastModifiedDate
        delete data.size
        delete data.chunks
        delete data.chunk
        delete data.file
        //当前分片索引 从1开始
        data.shardIndex = block.chunk + 1
        //总计分片数量
        data.shardTotal = block.chunks
        //上传单片内容
        data.shard = block.blob.source
        //文件名
        data.name = getFileName(block.file.name)
        //文件后缀
        data.suffix = getFileSuffix(block.file.name)
        //文件总大小
        data.size = block.file.size
        //分片大小(固定值)
        data.shardSize = that.options.chunkSize * 1024 * 1024
        //用途
        data.use = '视频上传'
        //UUID 唯一值区分
        data.key = block.file.guid
        deferred.resolve();
})

(3)自定义分片规则

/**
* startUpload(如秒传(后台通过文件的md5判断返回)秒传则触发UploadSkip) ==> uploadStart ==> uploadBeforeSend ==> uploadProgress ==> uploadAccept(接收服务器处理分块传输后的返回信息) ==> uploadSuccess ==> uploadComplete ==> uploadFinished*/
//当有文件被添加进队列的时候
uploader.on("fileQueued", function (file) {
   //获取分片规则
   let chunkSize = getChunkSize(file.size)
   //如果分片等于0不分片
   if(chunkSize > 0){
       //设置上传控件分配
       uploader.options.chunkSize = chunkSize
   }
   //是否分片
   uploader.options.chunked = chunkSize > 0;
})

(4)监听上传进度

/**
* 上传过程中触发,携带上传进度。
*/
uploader.on('uploadProgress',function(file, percentage){
    //修改上传状态逻辑
    var id = file.id
    var $current = that.$videoList.find(`#${file.identify}`)
    if(!$current) return 
    //文件名称
    let title = file.name
    //封面图地址
    let src = ''
    //视频唯一值
    let guid = file.guid
    //列表标识
    let identify = file.identify
    //进度
    let progress = (percentage * 100).toFixed(0)
    //状态
    let status = 0
    var html = miniTpl(createVideoLi(),{ id, src, title, guid, identify,progress, status})
    $current.html(html)
})

(5)上传完成监听事件

/**
     * 当文件上传成功时触发。
     */
    that.uploader.on('uploadSuccess', function(file, serverData){
        var id = file.id
        var $current = that.$videoList.find(`#${file.identify}`)
        //文件名称
        var title = file.name
        //视频唯一值
        var guid = file.guid
        //列表标识
        let identify = file.identify
        //进度100
        var progress = 100
        //封面地址
        var src = ''
        //文件上传状态
        var status = serverData.status ? 1 : 0
        //var html = yicheUtils.miniTpl(createVideoLi(),{ id, src, title, guid, identify, progress, status })
        //更新文件列表
        that.updateVideo(identify, { status, progress })
        //$current.html(html)
        that.upIndex++
        if(that.upIndex == that.options.videoList.length){
            //清上传索引
            that.upIndex = 0
        }
})

(6)上传错误处理

/*
* 当文件上传出错时触发。 
*/
uploader.on('uploadError',function(file){
        var id = file.id
        var $current = that.$videoList.find(`#${file.identify}`)
        var title = file.name
        var src = ''
        var progress = 0
        var status = -1
        var guid = file.guid
        //列表标识
        let identify = file.identify
        var html = miniTpl(createVideoLi(),{ id, src, title, guid, identify, progress, status })
        $current.html(html)
        //更新视频集合
        that.updateVideo(identify, { status: 0 })
})

(7)控件错误验证

/**
* 当validate不通过时,会以派送错误事件的形式通知调用者。通过
*/
uploader.on('error',function(type){
    var error = ''
    if (type == "Q_TYPE_DENIED") {
         error = '请上传'+ that.options.videoFormat.join(',') +'格式文件'
    } else if(type == "F_EXCEED_SIZE"){
         error = '文件大小不能超过'+  fileSizeUnit(that.options.fileSizeLimit)
    } else if(type == "Q_EXCEED_NUM_LIMIT"){
         error = '上传文件最多插入'+ that.options.fileNumLimit +'个视频'
    }
    //提示层
    that.toast(error)
})
//监听分块上传过程中的三个时间点
WebUploader.Uploader.register({
    //时间点1:所有分块进行上传之前调用此函数
    "before-send-file" : "beforeSendFile",
    //时间点2:如果有分块上传,则每个分块上传之前调用此函数
    "before-send" : "beforeSend",
    //时间点3:所有分块上传成功后调用此函数
    "after-send-file" : "afterSendFile",
 }
事件名参数说明描述
dndAccept
  • items {DataTransferItemList}

    DataTransferItem

阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API,且只能通过 mime-type 验证。

beforeFileQueued
  • file {File}

    File对象

当文件被加入队列之前触发。如果此事件handler的返回值为false,则此文件不会被添加进入队列。

fileQueued
  • file {File}

    File对象

当文件被加入队列以后触发。

filesQueued
  • files {File}

    数组,内容为原始File(lib/File)对象。

当一批文件添加进队列以后触发。

fileDequeued
  • file {File}

    File对象

当文件被移除队列后触发。

reset

当 uploader 被重置的时候触发。

startUpload

当开始上传流程时触发。

stopUpload

当开始上传流程暂停时触发。

uploadFinished

当所有文件上传结束时触发。

uploadStart
  • file {File}

    File对象

某个文件开始上传前触发,一个文件只会触发一次。

uploadBeforeSend
  • object {Object}
  • data {Object}

    默认的上传参数,可以扩展此对象来控制上传参数。

  • headers {Object}

    可以扩展此对象来控制上传头部。

当某个文件的分块在发送前触发,主要用来询问是否要添加附带参数,大文件在开起分片上传的前提下此事件可能会触发多次。

uploadAccept
  • object {Object}
  • ret {Object}

    服务端的返回数据,json格式,如果服务端不是json格式,从ret._raw中取数据,自行解析。

当某个文件上传到服务端响应后,会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为false, 则此文件将派送server类型的uploadError事件。

uploadProgress
  • file {File}

    File对象

  • percentage {Number}

    上传进度

上传过程中触发,携带上传进度。

uploadError
  • file {File}

    File对象

  • reason {String}

    出错的code

当文件上传出错时触发。

uploadSuccess
  • file {File}

    File对象

  • response {Object}

    服务端返回的数据

当文件上传成功时触发。

uploadComplete
  • file {File} [可选]

    File对象

不管成功或者失败,文件上传完成时触发。

error
  • type {String}

    错误类型。

当validate不通过时,会以派送错误事件的形式通知调用者。通过upload.on('error', handler)可以捕获到此类错误,目前有以下错误会在特定的情况下派送错来。

  • Q_EXCEED_NUM_LIMIT 在设置了fileNumLimit且尝试给uploader添加的文件数量超出这个值时派送。
  • Q_EXCEED_SIZE_LIMIT 在设置了Q_EXCEED_SIZE_LIMIT且尝试给uploader添加的文件总大小超出这个值时派送。
  • Q_TYPE_DENIED 当文件类型不满足时触发。。

至此视频上传功能,基本能实现。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
uniapp是一款非常流行的跨平台开发框架,可以用于快速开发多端应用。而在开发过程中,上视频是一个非常常见的需求。为了方便开发,有许多好用的上视频件可以使用。 其中比较常用的件有uni-upload、Uni-ImagePicker等。uni-upload是一个功能强大的多文件上组件,支持ajax上webuploader两种方式,同时也支持图片、音频和视频的上。Uni-ImagePicker则是一个图片选择器组件,它可以方便地实现从相册或摄像头中选择一张或多张图片的功能,同时也支持上视频。 在使用这些件时,首先需要在项目中引入对应件的依赖,然后在页面中使用对应的组件即可。在上视频时,可以通过设置一些参数来自定义上的行为,比如设置上视频的大小限制、格式限制等。上成功后,可以通过回调函数获取上成功后的视频地址,并将其显示在页面中。 需要注意的是,在上视频时,由于视频文件体积较大,可能需要一些时间才能完成上,因此需要设置一些提示信息,让用户知道上进度和状态。同时,也需要针对不同设备和网络情况做一些兼容性处理,保证上的稳定性和可靠性。 总之,通过使用uni-app的上视频件,可以快速方便地实现上视频的功能,提升应用的用户体验,为应用的开发和推广带来更多的便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值