接到上级指示,在文件管理系统中, 做一个拖拽文件夹上传功能, ,多的不说,少的不唠,上代码
此功能会新建所有文件夹,并将文件上传
表格用的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组件代码晚点贴
网友评论