vue实现h5自定义文件上传功能组件

自定义上传组件:文件上传与管理简易实现
本文介绍了一个简单的自定义文件上传功能组件,支持单文件上传,包括文件类型检查、大小限制及上传操作。组件尚未实现多文件上传和预览,按钮样式定制也暂未完成。

在 Web 开发中,文件上传是一个非常常见的需求。本文将介绍如何使用 Vue实现一个简单的自定义文件上传组件,并详细解释其实现原理和潜在的扩展方向。

概述

该组件实现了基本的文件上传功能,用户可以通过点击按钮选择文件并上传到服务器。此外,还提供了删除已上传文件的功能。尽管功能相对简单,但通过一些改进可以满足更多实际需求。

已实现功能:

  • 文件类型限制
  • 文件大小限制
  • 单文件上传
  • 上传后的文件显示与删除

待完善功能:

  • 多文件上传支持
  • 文件预览(如图片、PDF等)
  • 上传按钮样式自定义

核心代码

模板结构 <template>

<template>
    <div class="upload-box">
      <!-- 显示上传按钮和描述 -->
      <div v-show="!hideUpload">
        <div class="upload-wrapper">
          <div class="display-flex align-center">
            <img class="plus-icon" :src="require('../../assets/plus.png')" alt="">
            <span class="fileupload-text">添加</span>
          </div>
          <div class="file-desc">{{ text }}</div>
        </div>
        <!-- 隐藏的文件输入框 -->
        <input
          type="file"
          style="display:none"
          ref="file"
          @click="e => {e.target.value = '';}"
          :accept="accept"
          @change="getFileData"/>
      </div>

      <!-- 显示已上传文件信息 -->
      <div class="file-show" v-show="hideUpload">
        <div class="file-text">
          <img src="../../assets/file-icon.png" alt="">
          <span>{{ fileName }}</span>
        </div>
        <!-- 删除按钮 -->
        <img src="../../assets/clear-file.png" alt="" class="clear-icon" @click.stop="reUpload">
      </div>
    </div>
</template>
  • v-show="!hideUpload":控制是否显示上传按钮区域。
  • v-show="hideUpload":控制是否显示已上传文件的信息。

<script>

<script>
import { upLoad } from '../../utils/api/...'; // 假设这是你的上传接口

export default {
  name: "index",
  props: {
    text: { // 上传按钮文本
      type: String,
      default: "文件上传"
    },
    accept: { // 允许的文件类型
      type: String,
      default: ".doc,.docx,.pdf,.jpg,.jpeg,.gif,.png,.mp3,.mp4,.avi,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf"
    },
    applyType: { // 文件所属应用类型
      type: String,
      default: "application"
    },
    maxSize: { // 文件大小限制,默认2MB
      type: Number,
      default: 2
    },
    limit: { // 文件数量限制
      type: Number,
      default: 1
    }
  },
  data () {
    return {
      docType: { // 文档类型检查
        '.doc': 'application/msword',
        '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'pdf': 'application/pdf'
      },
      hideUpload: false, // 控制UI显示状态
      fileName: '' // 保存文件名
    }
  },
  methods: {
    clickUpload () {
      if (this.hideUpload === true) {
        // 如果已经上传了文件,则不触发新的上传
      } else {
        this.$refs.file.dispatchEvent(new MouseEvent("click")); // 触发文件选择对话框
      }
    },
    getFileData () {
      const inputFile = this.$refs.file.files[0]; // 获取选择的文件
      if (inputFile) {
        // 检查文件类型和大小
        if (!this.checkFileType(inputFile)) {
          this.$toast('请上传正确的文件类型');
          return;
        }
        if (inputFile.size > this.maxSize * 1024 * 1024) {
          this.$toast('文件大小已超出上传限制');
          return;
        }
        this.setUpload(inputFile.name, inputFile);
      } else {
        this.$toast('文件上传失败,请重试!');
      }
    },
    setUpload (name, file) {
      const formData = new FormData();
      formData.set("fileName", name);
      formData.set("file", file);
      upLoad(formData).then(res => {
        if (res.code === 200) {
          this.hideUpload = true;
          this.fileName = name; // 更新文件名显示
          this.$emit('getFile', res.data); // 向父组件传递数据
        } else {
          this.$toast('上传失败,请重试!');
        }
      }).catch(err => {
        this.$toast('上传失败,请重试!');
        console.error(err);
      });
    },
    reUpload () {
      this.$refs.file.value = null;
      this.hideUpload = false;
      this.$emit('getFile', {
        fileName: null,
        url: null
      });
    },
    checkFileType (file) {
      const accept = this.accept.split(',') || [];
      const fileType = '.' + file.type.split('/')[1];
      return accept.includes(fileType) || accept.includes(file.type);
    }
  }
}
</script>

<style scoped>

<style lang="scss" scoped>
.upload-box{
  margin: 40px auto;
}

.upload-wrapper{
  display: flex;
  flex-direction: column;
  align-items: center;
  .file-desc{
    max-width: 354px;
    color: #A2A2A2;
    font-size: 26px;
    text-align: center;
  }
}

.plus-icon{
  width: 42px;
  height: 42px;
  margin-right: 17px;
}

.fileupload-text{
  font-size: 28px;
  color: #797979;
}

.file-show{
  margin: 0 20px;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
}

.file-text{
  font-size: 26px;
  font-family: Microsoft YaHei, Microsoft YaHei-Regular;
  font-weight: 400;
  color: #797979;
  letter-spacing: 1.56px;
  margin-left: 25px;
}

.clear-icon{
  margin-left: 40px;
}
</style>

功能扩展建议

1. 多文件上传

  • 修改 limit 属性以允许上传多个文件。
  • methods.getFileData 中处理多个文件的选择。

2. 文件预览

  • 对于图片、PDF等文件类型,可以在上传后显示缩略图或直接嵌入页面进行预览。

3. 上传按钮样式自定义

  • 提供更多的 props 参数来允许用户自定义按钮的颜色、字体等样式。

总结

这个自定义文件上传组件虽然功能基础,但通过一些简单的修改就能适应更多的应用场景。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值