您的位置:

Vue上传视频

一、Vue上传视频文件

Vue上传视频文件是前端开发中非常重要的一环,该环节主要负责将视频文件上传至服务器。前端上传一般分为两步:1)获取视频文件2)上传文件。Vue框架最常见的形式是使用第三方插件vue-upload-component。

1.获取视频文件

获取视频文件可以使用input[type="file"]标签,但是该标签每次传输的文件大小有限制,还需要在每个上传按钮上重新设置。可以选择使用封装好的Vue组件,例如vue-upload-component,使用该组件可以让文件上传变得更容易。

<template>
   <VueUploadComponent 
      class="video-upload"
      extensions="mp4,mov" 
      :chunk-size="1024*1024+100"
      :multiple="true" 
      @input-file="onInputFile" 
      @on-start="onStart"
   >
     <div class="dropzone">拖放视频文件或者点击这里</div>
   </VueUploadComponent>
</template>

<script>
import VueUploadComponent from 'vue-upload-component';

export default {
  components: {VueUploadComponent},
  methods: {
    onStart () {
      console.log('Started...');
    },
    onInputFile (event) {
      console.log(event);
    }
  }
};
</script>

2.上传视频文件

上传文件一般使用FormData来封装表单数据以及文件。Vue中可以使用axios或者Vue-resource等http库来发送请求,并且封装好了上传文件所需的FormData。我们只需在Vue组件中绑定事件监听器并使用http库上传文件即可。

<template>
  <div>
    <input type="file" @change="uploadVideo" accept="video/*" />
  </div>
</template>

<script>
export default {
  methods: {
    uploadVideo (event) {
      const formData = new FormData();
      formData.append('video', event.target.files[0]);
      axios.post('/api/video', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(response => {
        console.log('Video uploaded!');
      });
    }
  }
};
</script>

二、Vue上传图片和视频

在Vue中同时上传图片和视频有两种方法:1)使用Vue-upload-component;2)使用HTML5多文件上传功能。

1.使用Vue-upload-component上传图片和视频

使用Vue-upload-component可以同时上传图片和视频,只需指定允许上传的文件类型,即可完成上传操作。

<template>
  <div>
    <VueUploadComponent :accept="'image/*, video/*'" id="file" :max-size="10 * 1024 * 1024" @input-file="onInputFile" />
  </div>
</template>

<script>
import VueUploadComponent from 'vue-upload-component';

export default {
  components: {VueUploadComponent},
  methods: {
    onInputFile () {
      console.log('File input!');
    }
  }
};
</script>

2.使用HTML5多文件上传功能

HTML5多文件上传功能可以将多个文件传输至服务器,但需要手动建立文件输入框并监听文件选择事件。

<template>
  <div>
    <input type="file" multiple="multiple" @change="uploadFiles" accept="image/*, video/*" />
  </div>
</template>

<script>
export default {
  methods: {
    uploadFiles (event) {
      const formData = new FormData();
      const files = event.target.files;
      for (let i = 0; i < files.length; i++) {
        formData.append(`file${i}`, files[i]);
      }
      axios.post('/api/upload', formData, {
        headers: {
          'content-type': 'multipart/form-data'
        }
      }).then(response => {
        console.log('Files uploaded!');
      });
    }
  }
};
</script>

三、Vue上传视频回显

Vue上传视频回显主要是将已上传的视频显示在页面上。视频回显有两种形式:1)预览图+链接下载;2)直接播放视频。

1.预览图+链接下载

预览图+链接下载是将上传的视频转换为预览图和下载链接的形式,直接点击预览图即可下载视频。预览图一般是视频的第一帧截图。

<template>
  <div v-for="video in videos">
    <img :src="video.cover" alt="video cover" />
    <a :href="downloadVideo(video.url)" download>Download</a>
  </div>
</template>

<script>
export default {
  methods: {
    downloadVideo (url) {
      return url.replace('videos/', 'download/');
    }
  }
};
</script>

2.直接播放视频

直接播放视频是在页面上直接显示上传的视频,使用HTML5 video标签即可实现。该方式比预览图+链接下载行为直观。

<template>
  <div v-for="video in videos">
    <video :src="video.url" controls></video>
  </div>
</template>

四、Vue上传视频和后台交互

上传视频到服务器时,需要和后台进行交互,将数据和文件传输给服务器。常用的方式有两种:1)前后端分离;2)后端封装。

1.前后端分离

前后端分离是将前端和后台分别进行开发,两者使用API进行交互。前端主要负责文件上传和接收与后台的交互数据来更新UI页面。后台负责接收文件和数据,进行文件存储和其他逻辑处理。

前端代码
<template>
  <div>
    <input type="file" @change="uploadVideo" accept="video/*" />
  </div>
</template>

<script>
export default {
  methods: {
    uploadVideo (event) {
      const formData = new FormData();
      formData.append('video', event.target.files[0]);
      axios.post('/api/video', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(response => {
        console.log('Video uploaded!');
      });
    }
  }
};
</script>
后端代码
const express = require('express');
const multer  = require('multer');
const path = require('path');

const app = express();

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/videos');
  },
  filename: (req, file, cb) => {
    cb(null, file.originalname);
  }
});

const upload = multer({ storage });

app.post('/api/video', upload.single('video'), (req, res) => {
  console.log('Video uploaded!');
  res.send();
});

app.listen(3000, () => {
  console.log('Server started!');
});

2.后端封装

后端封装是后台对上传文件进行封装,前端只需要调用对应的API即可完成文件上传和交互互动。该方式开发难度小,适用于小型应用。

<template>
  <div>
    <input type="file" @change="uploadVideo" accept="video/*" />
  </div>
</template>

<script>
export default {
  methods: {
    uploadVideo (event) {
      const formData = new FormData();
      formData.append('video', event.target.files[0]);
      axios.post('/api/video', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(response => {
        console.log('Video uploaded!');
      });
    }
  }
};
</script>

五、Vue上传视频获取视频信息

上传视频后,我们需要获取视频信息来进行后续操作。获取视频信息有两种方法:1)使用FFmpeg;2)使用浏览器原生API。

1.使用FFmpeg获取视频信息

FFmpeg是一个开源的视频处理工具,可以运行在各种操作系统上。使用Vue结合FFmpeg,可以直接在前端实现对上传视频的格式转换、视频截图等操作,但需要用户的浏览器支持WebAssembly。

<template>
  <div>
    <input type="file" ref="fileInput" @change="getVideoInfo" accept="video/*" />
  </div>
</template>

<script>
export default {
  methods: {
    getVideoInfo () {
      if (!this.$refs.fileInput.files.length) return;
      const file = this.$refs.fileInput.files[0];
      const ffm = createFFmpeg({
        log: true,
        progress: p => console.log(p)
      });

      ffm.load().then(() => {
        ffm.FS('writeFile', 'video.mp4', new Uint8Array(await response.arrayBuffer()));
        ffm.run('-i', 'video.mp4');
        const stdout = ffm.FS('readFile', 'stdout').toString();
        console.log(stdout);
      });
    }
  }
};
</script>

2.使用浏览器原生API获取视频信息

使用浏览器原生API可以获取视频的一些基本信息,例如视频截图、时长、大小等。

<template>
  <div>
    <input type="file" ref="fileInput" @change="getVideoInfo" accept="video/*" />
  </div>
</template>

<script>
export default {
  methods: {
    getVideoInfo () {
      if (!this.$refs.fileInput.files.length) return;
      const file = this.$refs.fileInput.files[0];
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onloadend = () => {
        const video = document.createElement('video');
        video.setAttribute('src', reader.result);
        video.load();
        video.onloadedmetadata = () => {
          console.log('Video duration:', video.duration);
          console.log('Video width:', video.videoWidth);
          console.log('Video height:', video.videoHeight);
        };
      };
    }
  }
};
</script>

六、Vue上传视频文件组件

为了方便重用,可以将Vue上传视频的相关代码封装为一个组件。组件的作用是将上传文件的过程封装起来,避免重复代码和页面实现的重复。

<template>
  <div>
    <input type="file" ref="fileInput" @input="onInputFile" accept="video/*" />
    <button @click="uploadVideo">Upload</button>
  </div>
</template>

<script>
export default {
  props: {
    url: {
      type: String,
      required: true
    }
  },
  data () {
    return {
      file: null
    };
  },
  methods: {
    onInputFile (event) {
      this.file = event.target.files[0];
    },
    uploadVideo () {
      if (!this.file) return;
      const formData = new FormData();
      formData.append('video', this.file);
      axios.post(this.url, formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(response => {
        console.log('Video uploaded!');
      });
    }
  }
};
</script>

七、Vue上传视频,获取时长

获取视频时长可以使用ffmpeg或者HTML5提供的duration属性。

1.使用FFmpeg获取时长

<script>
export default {
  methods: {
    async getVideoDuration () {
      const fileInput = this.$refs