26. Preview, download and dynamically delete components of vue project file attachments (only view without upload) - including mp4 preview, mp3 preview, image preview, PDF preview, etc.

Preview, download and dynamic deletion components of file attachments (only view without upload)

need

The requirement is to get an array of pictures, documents, video or audio arrays from the backend. The
final usage style screenshot is put at the end.
For example

fileList: [
        '/upload/332131.png',
        '/upload/sale?filename=csdacsa.pdf',
        '/upload/sale?filename=才能打死啊.xlx',
        '/upload/sale?filename=3.png',
        '/upload/sale?filename=吃的啥.gif',
        '/upload/sale?filename=除非是打完钱.zip',
        '/upload/等我if差动.mp4',
        '/upload/sale?filename=从电脑哦vcdai.mp3'
      ]

It needs to be able to be rendered to the page, and then be able to preview, including mp4, png, mp3, jpg, etc. The playback of video and audio is hard-coded. If the test file found on the Internet, if it is the backend, there is a specific return If you want to splice it yourself
insert image description here

File list list display component code

The plug-in for video playback needs to be installed and run in the terminal of the project root directory
npm install --save video.js

Import in the current page that needs to be used, and the global is not used here (it is definitely not because I have been reporting errors when using the global /(ㄒoㄒ)/~~)
import 'video.js/dist/video-js.css'

The current code import VideoJs from './VideoJs.vue'refers to the components in the same directory, that is, the following VideoJs.vuefiles

file-list.vue文件代码

<template>
  <div class="file-list">
    <div v-for="(item, index) in fileLists" :key="index" class="file">
      <div class="icon">
        <img v-if="getFileType(item) === 'xls' || getFileType(item) === 'xlsx'" src="@/static/file-icon/xls.png">
        <img v-else-if="getFileType(item) === 'doc' || getFileType(item) === 'docx'" src="@/static/file-icon/doc.png">
        <img v-else-if="getFileType(item) === 'mp3'" src="@/static/file-icon/mp3.png">
        <img v-else-if="getFileType(item) === 'mp4'" src="@/static/file-icon/mp4.png" @click="seeMp4(item)">
        <img v-else-if="getFileType(item) === 'pdf'" src="@/static/file-icon/pdf.png">
        <img v-else-if="getFileType(item) === 'ppt' || getFileType(item) === 'pptx'" src="@/static/file-icon/ppt.png">
        <img v-else-if="getFileType(item) === 'txt'" src="@/static/file-icon/txt.png">
        <img
          v-else-if="getFileType(item) === '7z' || getFileType(item) === 'zip' || getFileType(item) === 'rar'"
          src="@/static/file-icon/package.png"
        >
        <template v-else-if="getFileType(item) === 'jpg' || getFileType(item) === 'png' || getFileType(item) === 'gif'">
          <viewer>
            <img :src="baseUrl + item">
          </viewer>
        </template>
        <img v-else src="@/static/file-icon/other.png">
      </div>
      <el-button type="text" class="name" @click="check(item)">
        {
   
   { item }}
      </el-button>
      <div class="action">
        <a class="action-download" :href="baseUrl + item" download="" target="_self">下载</a>
        <span class="del" @click="handleDelete(index)">删除</span>
      </div>
      <!-- 弹窗预览文件 -->
      <el-dialog
        v-if="accessoryVisble"
        :visible.sync="accessoryVisble"
        :show.sync="accessoryVisble"
        width="60%"
        class="accessoryVisble"
        :before-close="cancel"
        top="40px"
        :title="checkFile"
        append-to-body
      >
        <div class="dialog">
          <div v-if="fileType === 1">
            <img :src="baseUrl + checkFile" width="100%" />
          </div>
          <div v-else-if="fileType === 2" class="audio-mp3">
            <audio controls ref="audio" class="aud">
              <source src="http://music.163.com/song/media/outer/url?id=447925558.mp3" />
            </audio>
          </div>
          <div class="videoArea" v-else-if="fileType === 3">
            <video-js :options="videoOptions" class="video-css" />
          </div>
          <div v-else-if="fileType === 5">
            <!-- <iframe :src="baseUrl + checkFile" frameborder="e" width="100%" height="600" /> -->
            <!-- 测试链接 -->
            <iframe :src="'http://www.leomay.com/upload/file/mmo-20170707165001.pdf'" frameborder="e" width="100%" height="600" />
          </div>
        </div>
      </el-dialog>
    </div>
  </div>
</template>

<script>
// 视频播放插件
import VideoJs from './VideoJs.vue'
import 'video.js/dist/video-js.css'
export default {
  name: 'fileList',
  props: {
    list: {
      type: [Array],
      default: () => []
    }
  },
  components: {
    VideoJs
  },
  data() {
    return {
      baseUrl: '/upload/sale?filename=',  // 这里需要使用自己的后端的基础地址
      fileLists: [],
      accessoryVisble: false,
      checkFile: '',
      fileType: null,
      /**
       *播放器配置,如果还需要其他的则再加
      */
      videoOptions: {
        controls: true, // 开启交互,即是用户可控。
        muted: true, // 开启视频时是否静音
        fluid: true, // 根据外层css样式大小,自动填充宽高!比较实用,可搭配响应式
        reload: 'auto', // 重载
        // 其余设置根据需求添加!
        poster: require('@/static/file-icon/mp4.png'), // 视频封面
        sources: [ // 视频播放源,建议本地
          {
            // 测试地址网上找的
            src: 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4',
            type: 'video/mp4'
          }
        ]
      }
    }
  },
  created() {
    // 获取文件名字格式列表
    for (let i = 0; i < this.list.length; i++) {
      console.log(this.getFileName(this.list[i]))
      this.fileLists.push(this.getFileName(this.list[i]))
      console.log(this.fileLists)
    }
  },
  methods: {
  	// 获取文件名字(分情况获取)
    getFileName(val) {
      if (val && val.indexOf('?filename=') !== -1) {
        console.log(val.substr(val.indexOf('?filename=') + 10))
        return val.substr(val.indexOf('?filename=') + 10)
      } else if (val && val.indexOf('upload/') !== 0) {
        const url = val.split('?')[0] // 只要?号前的
        const urlSlashCount = url.split('/').length // 统计斜杠
        console.log(url.split('/')[urlSlashCount - 1].toLowerCase())
        return url.split('/')[urlSlashCount - 1].toLowerCase() // 获取数组最后一个
        // return val
      } else {
        return val
      }
    },
    handleDelete(index) {
      console.log('删除', index)
      this.list.splice(index, 1)
    },
    handleDownload(index) {
      console.log('下载', index)
    },
    check(item) {
      console.log('预览', this.getFileType(item))
      this.checkFile = item
      this.accessoryVisble = true
      if (this.getFileType(item) === 'jpg' || this.getFileType(item) === 'png' || this.getFileType(item) === 'gif') {
        this.fileType = 1
        console.log('图片')
      } else if (this.getFileType(item) === 'mp3') {
        console.log('音频')
        this.fileType = 2
      } else if (this.getFileType(item) === 'mp4') {
        console.log('视频', this.videoOptions.sources[0].src)
        this.fileType = 3
        // this.videoOptions.sources.src[0] = this.baseUrl + item
      } else if (this.getFileType(item) === '7z' || this.getFileType(item) === 'zip' || this.getFileType(item) === 'rar') {
        console.log('压缩文件')
        this.checkFile = '该文件不可预览'
      } else {
        console.log('其他文件')
        this.fileType = 5
      }
    },
    cancel() {
      this.accessoryVisble = false
      this.otherFile = false
      this.isImage = false
      this.fileType = null
      this.checkFile = ''
    },
    //  获取文件格式
    getFileType(val) {
      const list = val.split('.')
      const type = list[list.length - 1]
      return type.toLowerCase()
    },
    seeMp4(item) {
      window.open(this.$settings.apiUrl + item)
    }
  }
}
</script>

<style lang="scss" scoped>
.file {
  display: flex;
  height: 48px;
  line-height: 48px;
  margin-bottom: 10px;

  .icon {
    margin-right: 10px;
    cursor: pointer;

    img {
      height: 48px;
      width: 36px;
      object-fit: cover;
    }
  }

  .name {
    flex: 1;
    display: flex;
    justify-content: flex-start;
  }

  .action {
    .del {
      color: red;
      cursor: pointer;
    }
    a {
      text-decoration-line: none;
      margin-right: 20px;
    }
      a:hover {
        text-decoration-line: underline;
      }
  }
}
  .dialog {
    width: 100%;
    // margin: auto;
    // display: flex;
    justify-content: center;
    align-items: center;
    margin-right: 20px;
    // height: auto;
    .videoArea {
      height: 100%;
    }
    .audio-mp3 {
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
</style>
<style>
单独给视频的播放按钮键设置位置
.video-js .vjs-big-play-button {
  top: 45%;
  left: 45%;
}
</style>

Video player componentVideoJs.vue

<template>
  <div>
    <video ref="videoPlayer" class="video-js"></video>
  </div>
</template>

<script>
import 'video.js/dist/video-js.css'
import videojs from 'video.js'
export default {
  // name: 'VideoJs',
  props: {
    options: {
      type: Object,
      default() {
        return {}
      }
    }
  },
  data() {
    return {
      player: null
    }
  },
  mounted() {
    this.player = videojs(this.$refs.videoPlayer, this.options, function onPlayerReady() {
      console.log('onPlayerReady', this)
    })
  },
  beforeDestroy() {
    if (this.player) {
      this.player.dispose()
    }
  }
}
</script>

<style scoped>
</style>

parent component reference

Just pass in the top fileList array

<template>
  <div>
    <file-list :list="fileList" />
  </div>
</template>

<script>
import fileList from './file-list.vue'
export default {
  components: {
    fileList
  },
  data() {
    return {
      fileList: [
         '/upload/332131.png',
        '/upload/sale?filename=csdacsa.pdf',
        '/upload/sale?filename=才能打死啊.xlx',
        '/upload/sale?filename=3.png',
        '/upload/sale?filename=吃的啥.gif',
        '/upload/sale?filename=除非是打完钱.zip',
        '/upload/等我if差动.mp4',
        '/upload/sale?filename=从电脑哦vcdai.mp3'
        '从电脑哦vcdai.mp3'
      ]
    }
  }
}
</script>

<style>

</style>

Audio Player

insert image description here

video playback

insert image description here

file view

The file view has not been carefully adjusted, you can test it yourself
insert image description here

picture view

insert image description here

Guess you like

Origin blog.csdn.net/qq_44035882/article/details/127531057