H5视频或文件上传与播放

386 阅读1分钟

背景

需求场景:

后台管理系统:

(1)配置中支持上传视频、上传成功后封面缩略图展示,点击后自动播放视频;

(2)配置中支持上传多个文件;

前台系统:

(1)展示视频列表并点击播放;

(2)展示文件列表并点击下载;

说明

看需求似乎很简单,再加上本身antd-design已经封装好的Upload组件,功能强大且丰富;但是具体需求场景中还是有不少交互细节,也花了一些时间调试,为以后碰到类似场景更快速高效实现,记录和分享出来

上传视频且展示缩略图

  1. 上传视频处理:

获取视频数据,并执行上传方法;一般二进制处理,可以支持各类文件格式,本质视频也是文件的一种格式;这一步其实很简单,参考Upload组件的相关实例即可,

<Upload
  multiple={true}
  fileList={videoList}
  listType="picture"
  beforeUpload={(file) => {
    const formData = new FormData();
    formData.append('file', file, file.name);
    request(`/upload/binary`, {
      method: 'post',
      body: formData,
    }).then((res: any) => {
      setVideoList([
        ...videoList,
        {
          name: file.name,
          url: res.data,
          thumbUrl: `${res?.data}`,
        },
      ]);
    });
  }}
  className={styles['upload-list-inline']}
>
  <Button icon={<UploadOutlined />}>上传视频</Button>
  <span className={styles['upload-tip']}>
    仅支持 rm,rmvb, wmv,avi, mpg, mpeg,mp4等格式,单个视频最大不得超过500M。
  </span>
</Upload>

上述代码listType字段设为“picture”,实例效果如下:

  1. 前台展示列表,demo代码如下:
<div className="introduction">
  <div className="app-message-title">视频教程</div>
  {videoList.map((item: FileProps, index: number) => {
    return (
      <div key={index} onClick={() => handleVideo(item)}>
         
        <img
          className="video-icon"
          src={require("icon.png")}
        />
        {/* <a href={item.url} className="file-name">
          {item.name}
        </a> */}
         <span className="file-name">
          {item.name}
        </span>
      </div>
    );
  })}
</div>

(1)实现代码如下:被注释掉的代码:交互效果,点击直接新开页

上传的不同尺寸,播放时按原视频的宽高:

缺点:新开页打开,不利于用户操作

(2)点击后弹窗展示,实现思路是使用antd的Modal组件,承载视频播放组件:

<Modal
  width={curVideo.width}
  bodyStyle={{ height: curVideo.height }}
  wrapClassName="video-modal"
  footer={null}
  visible={visible}
  onCancel={() => {
    setCurVideo(undefined);
    setVisble(false);
  }}
>
  <video src={curVideo.url} controls preload="auto" autoPlay={true} />
</Modal>
  1. 这里其实有一个问题,因为上传时不显示视频上传的像素,那么弹窗的宽高需要与视频的框高相同,所以上传的时候需要拿到视频的宽高:如何拿到视频宽高?
<Upload
  multiple={true}
  fileList={videoList}
  listType="picture"
  beforeUpload={(file) => {
    console.log('fiel = ', file);
    const videoUrl = URL.createObjectURL(file);
      const videoObj = document.createElement("video");
      videoObj.onloadedmetadata = function () {
          URL.revokeObjectURL(videoUrl);
           console.log("JJJJJ", videoObj.videoWidth, videoObj.videoHeight);  // 拿到视频的宽高
          // 执行上传的方法,获取外网路径,上传进度等
          const formData = new FormData();
          formData.append('file', file, file.name);
          request(`/upload/binary`, {
            method: 'post',
            body: formData,
          }).then((res: any) => {
           
            setVideoList([
              ...videoList,
              {
                name: file.name,
                url: res.data,
                thumbUrl: `${res?.data}`,  // 缩略图图片地址
                width: videoObj.videoWidth,  
                height: videoObj.videoHeight,
              },
            ]);
            

          });
      };
      videoObj.src = videoUrl;
      videoObj.load();
  }}
  className={styles['upload-list-inline']}
>
  <Button icon={<UploadOutlined />}>上传视频</Button>
  <span className={styles['upload-tip']}>
    仅支持 rm,rmvb, wmv,avi, mpg, mpeg,mp4等格式,单个视频最大不得超过500M。
  </span>
</Upload>

这样就解决了,Modal弹窗承载视频播放,Modal弹窗的宽高与视频的宽高一致;