美文网首页
仿windows拖拽上传文件

仿windows拖拽上传文件

作者: 老板下碗面 | 来源:发表于2024-05-11 11:49 被阅读0次

接到上级指示,在文件管理系统中, 做一个拖拽文件夹上传功能, ,多的不说,少的不唠,上代码

此功能会新建所有文件夹,并将文件上传
表格用的vxe,不相干的代码就不贴了

<vxe-table-column
    field="name"
    :title="$t('home.fileName')"
    min-width="300"
    show-overflow>
    <template v-slot="{ row }">
        <div
            id="target"
            style="text-overflow: ellipsis;"
            class="fs-13 fileName"
            :data-sir="row.type == '0' ? row.id : row.parentId"
            :data-type="row.type"
            :data-name="row.name"
            @click="hanldTable(row, 'db')"
            @dragover.prevent
            @drop="dropFolder($event, row)"
            @dragover="handleDragOver"
            @dragleave="handleDragLeave">
            <template>
             <svg-icon
                v-if="row.type == 0"
                class="file-icon folder-icon"
                icon-class="wenjianjia"/>
                <svg-icon
                    v-if="row.type == 1"
                    class="file-icon"
                :icon-class="$fileIcon(row.name)"/>
                <span v-if="row.isOnlyRead == 1"
                >({{ $t('cloud.efax.onlyRead') }})</span
                >
                <span
                    style="display: inline-block;width: 90%;"
                :data-sir="row.type == '0' ? row.id : row.parentId"
                :data-type="row.type"
                :data-name="row.name"
                :data-path="row.path">{{ row.name }}</span>
            </template>
        </div>
    </template >
</vxe - table - column >

:data-sir 和 :data-name 主要是用来拖入后变色用的

dropFolder(event, row) { //1,拖
    this.selectList = [];
    event.preventDefault();
    this.selectList.push(row);
    this.$message.success('开始解析文件夹');
    const items = event.dataTransfer.items;
    this.traverseFileTree(items);
    event.srcElement.style.backgroundColor = '#ffffff';
    event.target.style.backgroundColor = '';
},
traverseFileTree(items) { // 2.获取拖拽的目录或者文件
    let results = []
    for (let i = 0; i < items.length; i++) {
        const item = items[i].webkitGetAsEntry();
        if (item) {
            this.scanFileEntry(item, results);
        }
    }
},
scanFileEntry(entry, results) { //3.递归找出文件,文件夹
    let that = this;
    if (entry.isFile) {
        let fullPath = entry.fullPath;
        entry.file((file, i) => {
            file.fullPath = fullPath; //插入文件路径
            file['webkitRelativePaths'] = fullPath; //插入文件路径
            file.isFile = entry.isFile;
            results.push(file);
        })
        this.dropTimer = setTimeout(() => { //显示上传弹框
            console.log('可以开始上传了');
            that.configName = '确定';
            that.componentsName = 'dropUpload';
            that.btnType = 'dropUpload';
            that.dialogVisible = true;
            that.titleDialog = '上传';
            // 这里可以调用上传文件的函数,例如使用 FormData 进行上传
            that.$nextTick(() => {
                that.filterFiles(results); //处理获取到的所有文件,准备开始上传5.;
            })
        }, 2000)
    } else if (entry.isDirectory) {
        results.push(entry);
        const directoryReader = entry.createReader();
        this.readBatch(directoryReader, results);
    }
},
readBatch(directoryReader, results) { //4.重点,重点,重点,想要正常上传文件夹下超过100文件的必要逻辑
    directoryReader.readEntries(entries => {
        if (entries.length > 0) { //若超出100个,递归查询
            for (let i = 0; i < entries.length; i++) {
                clearTimeout(this.dropTimer);
                this.scanFileEntry(entries[i], results);
            }
            this.readBatch(directoryReader, results);
        }
    })
},
filterFiles(files) { //5.处理文件和文件夹, 把文件揪出来,添加目录信息, 把文件夹揪出来,方便上传文件夹后,文件找到目录
    //('上传')
    this.$nextTick(() => {
        this.api.document.path({ id: this.selectList[0].id }).then(res => {
            if (res.data.code == '0') {
                this.$refs.dropUpload.path = res.data.data.fullNamePath;
            }
        })
    })
    const fileArr = []; //文件集合
    const fileList = []; //文件集合
    const folderArr = []; //文件夹集合
    folderList = [];
    files.map(item => {
        if (item.isDirectory) {
            //文件夹
            folderList.push(item);
        } else if (item.isFile) {
            fileArr.push(item);
        }
    })

// 获取选择的文件夹及其所有子文件
      for (let i = 0; i < fileArr.length; i++) {
        const v = fileArr[i]
        //后缀是否合格
        if (v.webkitRelativePaths.indexOf('.') !== -1) {
          let folderPath = v.webkitRelativePaths.split('/')
          folderPath.splice(0, 1)
          let length = folderPath.length
          let parentName =
            length > 2
              ? `${folderPath[length - 3]}_${folderPath[length - 2]}`
              : `最高_${folderPath[length - 2]}`
          let level = folderPath.length - 1
          // 设置文件的基本信息
          fileList.push({
            file: v,
            name: v.name,
            size: v.size,
            type: '1',
            pLevel: level,
            parentName,
            status: 2,
            uploadTime: 0 //上传时间
          })
          this.sizeTotal = this.sizeTotal + Number(v.size)
          this.$refs.dropUpload.sizeTotal = this.sizeTotal
          this.remain = this.sizeTotal
          folderPath.splice(folderPath.length - 1, 1)
          folderPath.map((item, index) => {
            let obj = folderArr.filter(el => {
              if (folderPath.length > 1 && folderPath[index - 1] != undefined) {
                return (
                  item == el.name &&
                  index + 1 == el.level &&
                  el.packageName == `${folderPath[index - 1]}_${item}`
                )
              } else {
                return item == el.name && index + 1 == el.level
              }
            })
            if (!obj.length) {
              folderArr.push({
                type: '0',
                name: item,
                level: index + 1,
                parentName:
                  index > 1
                    ? `${folderPath[index - 2]}_${folderPath[index - 1]}`
                    : `最高_${folderPath[0]}`,
                packageName: folderArr.length
                  ? `${folderPath[index - 1]}_${item}`
                  : `最高_${item}`,
                status: 2
              })
            }
          })
        }
      }
      let list = this.sortList(folderList) //根据level 排序
      let folderData = this.sortList(folderArr) //上传文件夹中的[文件夹]集合
      this.uploadFileArr = [...folderData, ...fileList] //把文件夹和文件数据加入到表格中显示出来
      // this.$nextTick(()=>{
      this.$refs.dropUpload.initTabel(this.uploadFileArr, folderData, fileList)
      // })
    },
    sortList(arr) {
      const length = arr.length
      for (let i = 0; i < length - 1; i++) {
        for (let j = 0; j < length - 1 - i; j++) {
          let obj = null
          let obj2 = null
          if (arr[j].level > arr[j + 1].level) {
            obj = arr[j]
            obj2 = arr[j + 1]
            arr[j] = obj2
            arr[j + 1] = obj
          } else if (arr[j].level === arr[j + 1].level) {
            continue
          }
        }
      }
      return arr
    },

上传组件中发起上传的代码如下

selectFolders(file, folder) {
      let files = JSON.parse(JSON.stringify(file))
      this.returnList(files).then(res => {
        this.$refs.fileTable.loadData(res)
      })
      // this.uploadFolder(list) //开始上传动作 7x8x0
    },
    initTabel(list, folderData, fileList) {
      this.upLoadStatus = true
      //----判断缓存文件----------
      const pattern = /^~\$/
      let arr = list
      this.folderArr = folderData //上传文件夹中的[文件]集合
      let fileArr = []
      let storageFile = []
       fileList.map(item=>{
        if(pattern.test(item.name)){
          storageFile.push(item)
        }else{
          fileArr.push(item)
        }
      })
      this.storageFile = storageFile
      //---------------------------
      this.fileList = fileArr;
      this.uploadFileArr = arr
      this.returnList(arr).then(res => {
        this.$refs.fileTable.loadData(res)
      })
      this.uploadFolder(folderData) //开始上传动作 7x8x0
    },
    //*开始上传动作 7x8x1*
    uploadFolder(folderList) {
      this.sFileList = []
      let folderArr = folderList
      let parentId = null
      let name = null
      if (folderArr && folderArr.length) {
        name = folderArr[0].name //取文件夹名
        if (folderArr[0].level == 1) {
          parentId = this.list[0].id //首级文件夹,设置目录父id
        } else {
          let obj = this.folderList.filter(item => {
            return item.packageName == folderArr[0].parentName
          })
          parentId = obj[0].id
        }
        this.requestFolder(name, parentId, folderArr)
        this.status = 'folder'
      } else {
        this.uploadText = `文件夹全部上传完成! 准备上传文件`
        //文件夹新建完毕
        //开始传文件
        this.uploadFile(this.fileList)
        this.upStatus = 1
      }
    },
requestFolder(name, parentId, folderList) {
      //新建文件夹操作
      let arr = folderList.map(item => {
        return { ...item }
      })
      this.uploadText = `${name}文件夹,还剩${folderList.length - 1}个文件夹`
      this.api.document
        .addFolder({
          name,
          parentId
        })
        .then(res => {
          if (res.data.code == '0') {
            this.fList.push(name)
            this.folderList.push({
              //文件夹新建成功,加入到folderList  文件夹集合
              name,
              parentId,
              type: '0',
              id: res.data.data.id,
              level: folderList[0].level,
              packageName: `${arr[0].packageName}`
            })
            this.uploadFileArr.forEach(el => {
              //修改表格中状态,以便展示
              if (el.name == name && el.level == folderList[0].level) {
                el.status = 1
              }
            })
            this.expandRowKeys.push(res.data.data.id)
            this.$nextTick(() => {
              this.$refs.xTable.setTreeExpand(this.expandRowKeys, true)
            })
            arr.splice(0, 1) //请求集合数量减一,继续递归请求
            this.uploadFolder(arr) //递归,取设置参数
          } else {
            this.uploadFileArr.forEach(el => {
              if (el.name == name && el.level == folderList[0].level) {
                el.status = 0
              }
            })
            arr.splice(0, 1) //请求集合数量减一,继续递归请求
            this.uploadFolder(arr) //递归,取设置参数
          }
        })
    },
    uploadFile(fileList) {
      //传入文件集合,在已新建文件夹中寻找文件所在位置
      let fileArr = fileList
      if (fileArr && fileArr.length) {
        let params = {
          parentId: null,
          name: null,
          type: '1',
          file: fileArr[0].file,
          size: fileArr[0].size
        }
        params.name = fileArr[0].name
        if (this.folderList && this.folderList.length) {
          let obj = this.folderList.filter(item => {
            return (
              item.packageName == fileArr[0].parentName &&
              fileArr[0].pLevel == item.level
            )
          })
          params.parentId = obj[0].id
          this.requestFile(params, fileArr)
        } else {
          params.parentId = this.list[0].id
          this.requestFile(params, fileArr)
        }
      } else {
        let num = this.errorFiles
        // this.remain = 0
        this.status = 'folder'
        this.uploadText = `文件夹 和 文件全部上传完成!${
          this.errorFiles !== 0 ? '' : '如有失败文件请选择重新上传.'
        }`

        this.$message.success(`上传完成,失败${num}个,请检查`)
      }
    },
requestFile(params, fileList) {
      let uoloadTime = 0
      this.filename = params.name
      this.num = fileList.length
      this.status = 'file'
      this.uploadText = `文件夹全部上传完成! 正在上传`
      //上传文件操作
      let arr = fileList.map(item => {
        return { ...item }
      })
      this.uploadFileArr.forEach(el => {
        if (
          el.name == params.name &&
          el.pLevel == fileList[0].pLevel &&
          el.parentName == fileList[0].parentName
        ) {
          el.status = 3
          el.uoloadTime = uoloadTime
        }
      })
      this.progress = 0
      let timer = setInterval(() => {
        uoloadTime = uoloadTime + 1
      }, 1000)
      this.fileUpload(params)
        .then(res => {
          if (res.code == '0') {
            //成功
            clearInterval(timer)
            // this.uploadFileArr.push({ ...res.data, size: params.size, status: 1 })
            this.remain = this.remain - Number(params.size)
            this.uploadFileArr.forEach(el => {
              if (
                el.name == params.name &&
                el.pLevel == fileList[0].pLevel &&
                el.parentName == fileList[0].parentName
              ) {
                el.status = 1
              }
            })
            this.sFileList.push({
              name: res.data.name,
              parentId: res.data.parentId,
              type: '1'
            })
            this.returnList(this.uploadFileArr).then(res => {
              this.$refs.fileTable.loadData(res)
            })
            arr.splice(0, 1)
            this.uploadFile(arr)
          } else {
            //失败的
            // this.uploadFileArr.push({ ...params, status: 0 })
            let index, obj
            this.uploadFileArr.forEach((el, idx) => {
              if (
                el.name == params.name &&
                el.pLevel == fileList[0].pLevel &&
                el.parentName == fileList[0].parentName
              ) {
                el.status = 0
                index = idx
                obj = el
              }
            })
            if (index) {
              this.uploadFileArr.splice(index, 1)
              this.uploadFileArr.unshift(obj)
            }
            this.returnList(this.uploadFileArr).then(res => {
              this.$refs.fileTable.loadData(res)
            })
            this.remain = this.remain - Number(params.size)
            this.errorFiles++
            arr.splice(0, 1)
            this.uploadFile(arr)
          }
        })
        .catch(err => {
          let index, obj
          this.uploadFileArr.forEach((el, idx) => {
            if (
              el.name == params.name &&
              el.pLevel == fileList[0].pLevel &&
              el.parentName == fileList[0].parentName
            ) {
              console.log('[ el ]-520', el)
              el.status = 0
              index = idx
              obj = el
            }
          })
          if (index) {
            this.uploadFileArr.splice(index, 1)
            this.uploadFileArr.unshift(obj)
          }
          this.returnList(this.uploadFileArr).then(res => {
            this.$refs.fileTable.loadData(res)
          })
          this.remain = this.remain - Number(params.size)
          this.errorFiles++
          arr.splice(0, 1)
          this.uploadFile(arr)
        })
    },
fileUpload(params) {
      // 把body转成formData
      let formdata = new FormData()
      // formdata.append('fileSize', params.fileSize)
      // formdata.append('content', body.content)
      formdata.append('name', params.name)
      formdata.append('type', params.type)
      // formdata.append('index', body.index)
      formdata.append('file', params.file)
      // formdata.append('md5', body.md5)
      formdata.append('parentId', params.parentId)
      return axios({
        method: 'post',
        url: '/nas/file/upload',
        data: formdata,
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        onUploadProgress: progressEvent => {
          let progress = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          )
          if (progress > 95) {
            progress = 99
          }
          this.progress = progress
        }
      }).then(res => {
        this.progress = 100
        return res.data
      })
    },
    /* 文件大小显示 */
    getSize(size) {
      if (size === 0) {
        return '0KB'
      }
      if (!size && size != 0) {
        return '-'
      }
      size = (size / 1024).toFixed(2) * 1
      size = size < 1 ? 1 : size
      if (size > 1024) {
        size = size / 1024
        if (size > 1024) {
          size = (size / 1024).toFixed(2) * 1 + 'GB'
        } else {
          size = size.toFixed(2) * 1 + 'MB'
        }
      } else {
        size = size + 'KB'
      }
      return size
    }

这是处理文件代码
dropUpload组件代码晚点贴

相关文章

网友评论

      本文标题:仿windows拖拽上传文件

      本文链接:https://www.haomeiwen.com/subject/ashyfjtx.html