前端demo: COS上传图片、视频、文件的一些点

文章详细介绍了在HTML5环境下处理文件上传的策略,包括利用change事件检测文件变化,验证文件类型,判断文件大小,以及针对视频的特殊处理如更改文件格式。同时,文章探讨了获取视频时长的三种方法,并提供了全屏播放和禁止全屏的实现。此外,还涉及到了腾讯云对象存储(COS)的文件上传操作。
摘要由CSDN通过智能技术生成

1.选择相同视频未触发change事件


<input type="file" name="file" id="file" />

<script>
    // 在适当时机克隆input元素后移除原来的input
    $("#file").after($("#file").clone().val("")).remove();
</script>

参考:INPUT[type=file]的change事件不触发问题_风神修罗使的博客-CSDN博客

2.监听change事件判断文件类型

    function bindChangeEvent() {
      $(document)
        .off("change")
        .on("change", "#file", function () {
          var fileObj = $(this);
          if (fileObj.val().length < 1) return;

          var file = fileObj[0].files["0"];
          if (!file) return;

          const type = file.type;
          const supportedTypes = ["video", "image", "rar", "zip"];

          if (type && !supportedTypes.some((e) => type.includes(e))) {
            alert("暂不支持上传");
            return;
          }

          // rar文件类型的type为空,此时根据文件名后缀判断
          if (!type && !/\.rar$/.test(file.name)) {
            alert("暂不支持上传");
            return;
          }

          if (type.includes("image/")) {
            uploadPic(file); // todo: 上传图片
          } else {
            uploadFile(file, type); // todo: 上传文件
          }
        });
     }

3.判断文件大小

   function isSopportSize(file, size) {
        if (file.size.toFixed(2) > size * 1024 * 1024) {
          alert(`请选择小于${size}MB的文件`);
          return false;
        }
        return true
      }

4.上传Key为mov格式文件到COS无法播放,特殊处理改为mp4

   if (/\.(mov|MOV)$/.test(file.name)) {
        fileName = file.name.replace(/\.(mov|MOV)$/, '.mp4')
    }

5.cos 实例调用 COS 请求

    // cos 实例调用 COS 请求
    cos.uploadFile(
        {
            Bucket,
            Region,
            Body: file,
            SliceSize: 1024 * 1024 * 5, // 分块上传会多次调用 new COS中传入的getAuthorization
            ContentType: type,  // 添加上传的文件类型,COS会根据该类型设置Content-Type
            Key: fileName,
            ...

        })

6.获取视频时长的3种方法

使用HTML5的File API和Video API:

    <input type="file" id="videoInput" accept="video/*" />

    <script>
      var videoInput = document.getElementById("videoInput");

      videoInput.addEventListener("change", function () {
        var file = this.files[0];
        var video = document.createElement("video");
        var url = URL.createObjectURL(file);

        video.src = url;
        video.addEventListener("loadedmetadata", function () {
          console.log("视频时长:", video.duration);
        });
      });

    // var audioElement = new Audio(URL.createObjectURL(file));
    // audioElement.muted = true;
    // audioElement.play().then(() => audioElement.pause());

    // audioElement.addEventListener(
    //   "loadedmetadata",
    //   function () {
    //     console.log("视频时长:", audioElement.duration);
    //     audioElement.muted = false;
    //   }
    // );

    </script>
  • 使用第三方库如`video.js`进行视频播放和获取时长:
    <input type="file" id="videoInput" accept="video/*" />

    <script src="https://vjs.zencdn.net/7.14.3/video.js"></script>
    <link href="https://vjs.zencdn.net/7.14.3/video-js.css" rel="stylesheet" />

    <script>
      var videoInput = document.getElementById("videoInput");

      videoInput.addEventListener("change", function () {
        var file = this.files[0];
        var video = document.createElement("video");
        var player = videojs(video);

        player.on("loadedmetadata", function () {
          console.log("视频时长:", player.duration());
        });

        var reader = new FileReader();
        reader.onload = function (e) {
          player.src({
            src: e.target.result,
            type: "video/mp4",
          });
        };
        reader.readAsDataURL(file);
      });
    </script>
  • 使用ffmpeg.js进行视频解码和获取时长(需要将视频文件上传到服务器进行解码):
<input type="file" id="videoInput" accept="video/*" />

    <script src="https://cdnjs.cloudflare.com/ajax/libs/ffmpeg.js/1.8.4/ffmpeg.min.js"></script>

    <script>
      var videoInput = document.getElementById("videoInput");

      videoInput.addEventListener("change", function () {
        var file = this.files[0];
        var video = document.createElement("video");
        var url = URL.createObjectURL(file);

        video.src = url;
        video.addEventListener("loadedmetadata", function () {
          // 使用ffmpeg.js进行视频解码
          ffmpeg.FS("writeFile", "input.mp4", new Uint8Array(file));
          ffmpeg.run("-i input.mp4", "-hide_banner", function (output) {
            var regex = /duration (\d+:\d+:\d+)/;
            var duration = output.match(regex)[1];
            console.log("视频时长:", duration);
          });
        });
      });
    </script>

 注意:

7.时长和文件单位工具函数

  // 文件单位转换
    filesizeConvert(size) {
        var data = ''
        if (size < 0.1 * 1024) {
            data = size.toFixed(2) + 'B'
        } else if (size < 0.1 * 1024 * 1024) {
            data = (size / 1024).toFixed(2) + 'KB'
        } else if (size < 0.1 * 1024 * 1024 * 1024) {
            data = (size / (1024 * 1024)).toFixed(2) + 'MB'
        } else {
            data = (size / (1024 * 1024 * 1024)).toFixed(2) + 'GB'
        }
        var sizestr = data + ''
        var len = sizestr.indexOf('.')
        var dec = sizestr.substr(len + 1, 2)
        if (dec == '00') {
            return sizestr.substring(0, len) + sizestr.substr(len + 3, 2)
        }
        return sizestr
    },
    // 视频格式化
    formatDuraton(time) {
        if (time > -1) {
            var hour = Math.floor(time / 3600)
            var min = Math.floor(time / 60) % 60
            var sec = time % 60
            if (hour < 10) {
                time = '0' + hour + ':'
            } else {
                time = hour + ':'
            }

            if (min < 10) {
                time += '0'
            }
            time += min + ':'

            if (sec < 10) {
                time += '0'
            }
            time += sec
        }
        return time
    },

8.视频和进度条模板

<style>
  /* 上传圆形进度条 */
  .upload-loading {
    width: 46px;
    height: 46px;
    padding: 20px;
    position: relative;
    overflow: hidden;
    border-radius: 50%;
    line-height: 46px;
    text-align: center;
    font-size: 10px;
    color: #fff;
  }
  .upload-loading strong {
    font-weight: normal;
  }
  .upload-loading canvas {
    position: absolute;
    top: 20px;
    left: 20px;
  }
</style>

<script>
  function setVideoHtml(message) {
    const { url, isFirst, task_Id, isSuccess, duration } = message;
    const isWechat = isWechat();
    const isAndroid = isAndroid();
    let cosUrl = `https://${url}`;
    cosUrl = isAndroid ? cosUrl : cosUrl + "#t=0.1";
    const mySrc = `${isFirst ? url : cosUrl}`;
    const isShowControls = isFirst || !isSuccess;

    return `<div data-taskId=${task_Id} class="video-main">
          <video controlsList="nodownload" disablePictureInPicture id="videoPlayer" initial-time="0.01" preload="metadata" ${
            isAndroid || isWechat
              ? `x5-video-orientation="portrait" x5-video-player-fullscreen="true" x5-video-player-type="h5" poster="${mySrc}?vframe/jpg/offset/1"`
              : ""
          }
         style="border-radius:8px;vertical-align:middle;max-width:158px;max-height:158px;${
           isAndroid || isWechat ? "min-height:90px;" : "width:auto;height:auto"
         }">
              <source src="${url}" type="video/mp4">
              <source src="${url}" type="video/webm">
              <source src="${url}" type="video/ogg">
              您的浏览器不支持 HTML5 video 标签。
          </video>
          <span>${duration}</span>
          ${
            isFirst
              ? `<div class="loading middle">${setCircleLoadingHtml(
                  task_Id
                )}</div>`
              : ""
          }
      </div>`.replace(/\n/gm, "");
  }
  function setCircleLoadingHtml(task_Id) {
    return `<div class="upload-loading">
          <strong id="number">0%</strong>
          <canvas width="46" height="46" id="ccb-${task_Id}"></canvas>
          <canvas width="46" height="46" id="ccc-${task_Id}"></canvas>
        </div>`.replace(/\n/gm, "");
  }
</script>

9.绘制上传进度的进度条 

// 绘制进度条
function loadingCanvas(taskId) {
    var c1 = document.getElementById(`ccb-${taskId}`) // 进度条
    var ctx1 = c1.getContext('2d')
    ctx1.strokeStyle = 'rgb(123,165,236)'
    ctx1.lineWidth = 4

    var c = document.getElementById(`ccc-${taskId}`) // 进度条背景
    var ctx = c.getContext('2d')
    ctx.beginPath()
    ctx.lineWidth = 4
    ctx.strokeStyle = 'rgba(182,197,223,.5)'
    ctx.arc(23, 23, 20, 0, 2 * Math.PI)
    ctx.stroke()
    return ctx1
}
// 进度条加载中
function loadingPercent(percent, ctx1, data_taskId) {
    ctx1.beginPath() // 开始画图
    ctx1.clearRect(0, 0, 210, 210) // 清除画布
    $(`${data_taskId} #number`).text(percent.toFixed(0) + '%')
    ctx1.arc(23, 23, 20, -0.5 * Math.PI, (1.5 * Math.PI * percent) / 100)
    ctx1.stroke()
}

10.全屏播放

    function bindVideo (data_taskId) {
        $(`${data_taskId} .play`).show()
        $(`${data_taskId} video`).attr({ controls: false })
        const elvideo = $(`${data_taskId} video`)[0]

        $(`${data_taskId} .play`)
            .off('click')
            .on('click', (e) => {
                $(`${data_taskId} video`).attr({ controls: true })
                $(`${data_taskId} .play`).hide()
                $(`${data_taskId} span`).hide()

                if (isAndroid()) {
                    requestFullScreen() // 安卓视频播放不自动全屏,特殊处理
                }

                if (isMinigram()) {
                    elvideo.muted = true // 设置静音
                    $(`${data_taskId} video`).attr('autoplay', true)
                    $(`${data_taskId} video`).load()
                } else {
                    elvideo.play()
                }
            })

        // 视频全屏按钮点击事件
        elvideo.addEventListener('fullscreenchange', () => {
            var fullScreenElement = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement
            // var orientation = window.orientation

            if (fullScreenElement) {
                // 全屏时的处理逻辑
                // console.log('进入全屏')
                // console.log('全屏元素:', fullScreenElement)
                //要获取全屏横竖屏方向,您可以使用window.orientation属性。该属性返回显示屏幕方向的数值,其中0表示竖屏,90表示逆时针旋转90度,-90表示顺时针旋转90度。
                // console.log('屏幕方向:', orientation)
            } else {
                // 退出全屏时的处理逻辑
                // console.log('退出全屏')
                elvideo.pause()
                $(`${data_taskId} video`).attr({ controls: false })
                $(`${data_taskId} video`).attr('autoplay', false)
                $(`${data_taskId} .play`).show()
                $(`${data_taskId} span`).show()
            }
        })

        // 调用requestFullscreen方法实现全屏
        function requestFullScreen() {
            if (elvideo.requestFullscreen) {
                elvideo.requestFullscreen()
            } else if (elvideo.mozRequestFullScreen) {
                elvideo.mozRequestFullScreen() //FireFox
            } else if (elvideo.webkitRequestFullscreen) {
                elvideo.webkitRequestFullscreen() //Chrome等
            } else if (elvideo.msRequestFullscreen) {
                elvideo.msRequestFullscreen() //IE11
            }
        }
    
    },

11获取视频第一帧

// 获取video元素
var video = document.getElementById('video');
// 创建canvas元素
var canvas = document.createElement('canvas');
// 设置canvas的宽度和高度
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
// 获取canvas的上下文
var ctx = canvas.getContext('2d');
// 将video的第一帧画到canvas上
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
// 获取第一帧的图像数据
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
<video id="myVideo" width="320" height="240" controls>
  <source src="movie.mp4" type="video/mp4">
</video>
<script>
  var video = document.getElementById("myVideo");
  video.currentTime = 0;
</script>

12强制禁用全屏按钮

在H5的video标签中,可以通过设置x5-video-player-fullscreen属性为false来禁用全屏按钮,避免出现方向冲突问题

<video src="video.mp4" controls x5-video-player-fullscreen="false"></video>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值