智能文件上传系统设计:融合繁体简化与内容级去重机制

65 阅读2分钟
  1. 安装spark-md5用来校验文件内容,禁止上传文件内容一致的文件
npm install spark-md5
# 或者
yarn add spark-md5
  1. 安装opencc-js,将上传的文件名称由繁体改为简体
npm install opencc-js
  1. upload上传组件(自行安装并在main.js中use使用element-ui即可)
<template>
  <div>
    <el-upload
      class="upload"
      drag
      action=""
      :auto-upload="false"
      :show-file-list="false"
      :on-change="handleFileChange"
      :http-request="uploadFile"
      multiple
      ref="upload"
    >
      <div class="icon-upload"></div>
      <div class="upload-btn"></div>
      <div class="el-upload__text">将文件拖到此处或<em>点击上传</em></div>
    </el-upload>
    <!-- 展示已选文件并支持单个删除 -->
    <div class="file-list-container" v-if="selectedFiles.length > 0">
      <div class="file-list-header">已选文件</div>
      <div class="file-list-grid">
        <div
          class="file-item"
          v-for="(file, index) in selectedFiles"
          :key="index"
        >
          <span class="file-name">{{ file.name }}</span>
          <!-- 删除按钮 -->
          <el-button
            class="delete-btn"
            type="text"
            icon="el-icon-delete"
            @click.stop="removeSingleFile(index, file.name)"
          ></el-button>
        </div>
      </div>
    </div>
  </div>
</template>
  1. JS方法逻辑
<script>
// 校验内容所用
import SparkMD5 from "spark-md5";
// 文件名称繁转简
import { Converter } from "opencc-js";
export default {
  data() {
    return {
      fileListData: [], // el-upload内部文件列表
      selectedFiles: [], // 选择的文件名称列表(如果页面需要展示已选文件名)
    };
  },
  methods: {
    async handleFileChange(file, fileList) {
      // 繁体转简体(如果文件上)
      // 防止eslint报错 引入openCC后将OpenCC.Converter改为Converter
      // const converter = await OpenCC.Converter({ from: "hk", to: "cn" });
      const converter = await Converter({ from: "hk", to: "cn" });
      const simplifiedName = converter(file.name);

      // 读取文件内容并生成 MD5
      const md5 = await this.calculateFileMD5(file.raw);

      // 判断内容是否重复(通过 MD5)
      const duplicateContent = this.fileListData.some((f) => f.md5 === md5);
      if (duplicateContent) {
        this.$message.warning("请勿上传内容相同的文件");
        return;
      }

      // 判断文件名是否重复
      const duplicateName = this.fileListData.some(
        (f) => f.name === simplifiedName
      );
      if (duplicateName) {
        this.$message.warning("请勿上传相同名称的文件");
        return;
      }

      // 构造简体名称的新 File 对象,强制将文件名称改为简体,不需要则去掉此代码
      const newFile = new File([file.raw], simplifiedName, {
        type: file.raw.type,
        lastModified: file.raw.lastModified,
      });

      // 添加到文件列表
      this.fileListData.push({
        ...file,
        name: simplifiedName,
        raw: newFile,
        md5,
      });

      // 已选择文件名称组成的列表(如果需要)
      this.selectedFiles = this.fileListData.map((f) => f.raw);
    },
    // 收集上传的文件
    uploadFile(file) {
      this.fileData.push(file);
    },
    // 删除按钮
    removeSingleFile(index, filename) {
      this.selectedFiles.splice(index, 1);
      // 同时更新el-upload的内部文件列表
      this.$refs.upload.uploadFiles.splice(index, 1);
      this.fileListData = this.fileListData.filter((file) => {
        return file.name !== filename;
      });
    },
    // 用于给文件生成MD5
    async calculateFileMD5(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = function (e) {
          const spark = new SparkMD5();
          spark.appendBinary(e.target.result);
          resolve(spark.end());
        };
        reader.onerror = function () {
          reject("文件读取失败");
        };
        reader.readAsBinaryString(file);
      });
    },
  },
};
</script>