最近在写一个选择文件夹对文件夹下的PDF进行统计的功能,试过很多方法就是获取不到绝对路径,用input标签里的webkitRelativePathwebkitRelativePath只能获取一层的目录。
快要放弃的时候看到了一位博主发的用后端获取每一层的目录列表,前端自己写一个选择文件夹的对话框,经过修改成功获取到了文件夹的绝对路径。
效果展示
后端逻辑代码
这是一段在Service服务层的逻辑代码,可根据自己需要进行改造,没有写访问路径,前端的getFileList访问的就是这段逻辑代码的路径
public Result<?> fileList(String path) {
// 创建一个存储文件名的列表
List<String> fileName = new ArrayList<>();
// 如果传入的路径为空,获取所有磁盘根目录
if ("".equals(path)) {
// 使用文件系统视图来获取系统的文件系统信息
FileSystemView fsv = FileSystemView.getFileSystemView();
// 获取所有磁盘根目录(如C:、D:等)
File[] fs = File.listRoots();
// 遍历所有磁盘根目录
for (int i = 0; i < fs.length; i++) {
// 获取每个磁盘的显示名称(包括盘符和卷标)
String name = fsv.getSystemDisplayName(fs[i]).toString();
if (!name.isEmpty()) {
// 提取显示名称中的盘符部分,假设名称格式类似于 "Local Disk (C:)"
int begin = name.lastIndexOf("(");
int end = name.lastIndexOf(")");
name = name.substring(begin + 1, end); // 获取括号内的盘符
fileName.add(name); // 将盘符添加到文件名列表中
}
}
// 返回包含所有磁盘盘符的结果
return Result.OK(fileName);
} else {
// 如果传入的路径不为空,获取该目录下一级的所有文件夹
String dirName = path;
File file = new File(dirName);
// 检查路径是否是一个目录
if (file.isDirectory()) {
// 获取目录下的所有文件和文件夹的名称列表
String[] list = file.list();
if (list == null) {
return Result.error("此文件夹不能访问");
} else {
// 遍历该目录下的文件和文件夹
for (int i = 0; i < list.length; i++) {
File file2 = new File(dirName + "\\" + list[i]);
// 如果是文件夹,则将其名称添加到文件名列表中
if (file2.isDirectory()) {
fileName.add(list[i]);
}
}
// 返回包含该目录下所有子文件夹名称的结果
return Result.OK(fileName);
}
} else {
// 如果传入的路径不是目录,返回错误信息
return Result.error("不是一个目录");
}
}
}
前端对话框
我没有把对话框和整个页面写在一起,有些数据用到了父子组件的通信,可能没有删除完全,但是答题思路就是这样。
<template>
<a-modal title="选择路径" v-model:open="showDialog" width="60%" @cancel="closeGetPath">
<a-form layout="vertical">
<a-form-item>
<a-input v-model:value="filePath" size="middle" style="width: calc(100% - 100px); margin-left: 4px" placeholder="请选择路径" />
<a-button size="middle" @click="backRoute" preIcon="ant-design:arrow-left" danger> 后退 </a-button>
</a-form-item>
</a-form>
<div class="scroll-container">
<a-row>
<a-col :span="6" v-for="(item, index) in fileList" :key="index" class="gutter-row">
<div class="gutter-box">
<a-tooltip :title="fileList[index]" color="green">
<a-input v-model:value="fileList[index]" @click="clickData(fileList[index])" type="button" style="margin-bottom: 10px; width: 100%" />
</a-tooltip>
</div>
</a-col>
</a-row>
</div>
<template #footer>
<a-button @click="closeGetPath" size="middle">取消</a-button>
<a-button type="primary" @click="confirmRoute" size="middle"> 确定 </a-button>
</template>
</a-modal>
</template>
<script setup lang="ts">
import { message } from 'ant-design-vue';
import { onUpdated, ref, watch } from 'vue';
import { getFileList } from '@/views/archivesProcess/statistic/statistic.api';
const fileList = ref({});
const filePath = ref('');
const showDialog = ref(false);
// 获取路径的方法
const handleGetPath = async () => {
await getFileList({ data: filePath.value })
.then((res) => {
if (res.success == true) {
fileList.value = res.result;
} else {
message.error(res.message);
}
})
.catch(() => {
message.error('获取路径失败');
});
};
// 关闭窗口
function closeGetPath() {
filePath.value = '';
fileList.value = {};
}
// 确定按钮
function confirmRoute() {
closeGetPath();
}
// 点击进入文件列表
function clickData(fileName) {
if (filePath.value === '') {
filePath.value = fileName + '\\';
} else {
// 检查路径末尾是否已经有反斜杠
if (!filePath.value.endsWith('\\')) {
filePath.value += '\\';
}
filePath.value += fileName;
}
getFileList({ data: filePath.value })
.then((res) => {
if (res.success == true) {
fileList.value = res.result;
} else {
message.error(res.message);
backRoute();
}
})
.catch(() => {
message.error('获取路径失败');
});
}
// 向上一级
function backRoute() {
if (filePath.value === '') {
message.error('未选择路径');
} else {
if (filePath.value.length <= 3) {
filePath.value = '';
} else {
filePath.value = filePath.value.substring(0, filePath.value.lastIndexOf('\\'));
//此处是防止到一级目录少\\
if (filePath.value.length <= 3) {
filePath.value = filePath.value + '\\';
}
}
}
getFileList({ data: filePath.value })
.then((res) => {
if (res.success == true) {
fileList.value = res.result;
} else {
message.error(res.message);
}
})
.catch(() => {
message.error('获取路径失败');
});
}
watch(
() => props.visible,
(val) => {
showDialog.value = val;
}
);
onUpdated(() => {
if (showDialog.value == true) {
handleGetPath();
}
});
</script>
<style scoped lang="less">
.scroll-container {
max-height: 300px;
overflow-y: auto;
padding: 10px 0;
}
.gutter-row {
margin-bottom: 10px;
}
a-input {
border-radius: 4px;
border: 1px solid #d9d9d9;
width: 100%; /* 确保宽度占满容器 */
}
a-button {
border-radius: 4px;
}
a-modal {
padding: 10px;
}
a-modal-title {
font-weight: bold;
font-size: 18px;
}
.gutter-box {
padding: 0px 4px 0px 4px;
}
</style>