SSM框架分页展示HDFS文件列表,上传文件,删除文件,下载文件,进入下一级,返回上一级前后端代码
时间: 2023-06-12 18:05:52 浏览: 217
这是一个比较复杂的问题,需要分步骤进行介绍。以下是基本的实现步骤和前后端代码:
1. 配置Hadoop客户端
在SSM项目中,需要配置Hadoop客户端,以便连接远程HDFS文件系统。可以参考以下代码:
```java
@Configuration
public class HadoopConfig {
@Value("${hadoop.fs.defaultFS}")
private String defaultFS;
@Value("${hadoop.user}")
private String user;
@Bean
public FileSystem fileSystem() throws IOException {
Configuration configuration = new Configuration();
configuration.set("fs.defaultFS", defaultFS);
System.setProperty("HADOOP_USER_NAME", user);
return FileSystem.get(configuration);
}
}
```
在application.properties文件中,需要配置以下参数:
```properties
hadoop.fs.defaultFS=hdfs://192.168.0.100:9000
hadoop.user=hadoop
```
2. 分页展示HDFS文件列表
可以使用Hadoop的FileSystem API来获取HDFS文件列表,然后将其转换为JSON格式返回给前端进行展示。以下是基本的后端代码:
```java
@GetMapping("/list")
public ResultVO list(@RequestParam(value = "path", defaultValue = "/") String path,
@RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
@RequestParam(value = "pageNum", defaultValue = "1") int pageNum) throws IOException {
FileSystem fileSystem = fileSystem();
Path hdfsPath = new Path(path);
FileStatus[] fileStatuses = fileSystem.listStatus(hdfsPath);
List<Map<String, Object>> fileList = Arrays.stream(fileStatuses)
.map(fileStatus -> {
Map<String, Object> fileInfo = new HashMap<>();
fileInfo.put("name", fileStatus.getPath().getName());
fileInfo.put("path", fileStatus.getPath().toString());
fileInfo.put("isDirectory", fileStatus.isDirectory());
fileInfo.put("length", fileStatus.getLen());
fileInfo.put("modificationTime", fileStatus.getModificationTime());
return fileInfo;
})
.collect(Collectors.toList());
int total = fileList.size();
int startIndex = (pageNum - 1) * pageSize;
int endIndex = Math.min(startIndex + pageSize, total);
List<Map<String, Object>> pageList = fileList.subList(startIndex, endIndex);
return ResultVO.success(Map.of("pageList", pageList, "total", total));
}
```
前端需要发送GET请求,获取HDFS文件列表数据,然后使用Vue的分页组件进行展示。以下是基本的前端代码:
```html
<template>
<div class="file-list">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Size</th>
<th>Last Modified</th>
</tr>
</thead>
<tbody>
<tr v-for="fileInfo in pageData" :key="fileInfo.path">
<td>
<a v-if="fileInfo.isDirectory" @click="enterDirectory(fileInfo.path)">
<i class="fa fa-folder"></i> {{ fileInfo.name }}
</a>
<a v-else href="#" @click="downloadFile(fileInfo.path)">
<i class="fa fa-file"></i> {{ fileInfo.name }}
</a>
</td>
<td>{{ fileInfo.isDirectory ? 'Directory' : 'File' }}</td>
<td>{{ formatFileSize(fileInfo.length) }}</td>
<td>{{ formatDateTime(fileInfo.modificationTime) }}</td>
</tr>
</tbody>
</table>
<pagination :page-count="totalPage" :current-page="currentPage" @page-change="handlePageChange" />
</div>
</template>
<script>
import Pagination from "@/components/Pagination";
export default {
components: {
Pagination,
},
data() {
return {
pageData: [],
totalPage: 0,
currentPage: 1,
};
},
methods: {
async loadPageData(path, pageSize, pageNum) {
const response = await this.$axios.get("/file/list", {
params: { path, pageSize, pageNum },
});
if (response.data.code === 0) {
const data = response.data.data;
this.pageData = data.pageList;
this.totalPage = Math.ceil(data.total / pageSize);
this.currentPage = pageNum;
}
},
handlePageChange(newPage) {
this.loadPageData(this.currentPath, this.pageSize, newPage);
},
},
mounted() {
this.loadPageData("/", 10, 1);
},
};
</script>
```
3. 上传文件
可以使用Hadoop的FileSystem API来实现文件上传,将前端传递过来的文件保存到HDFS文件系统中。以下是基本的后端代码:
```java
@PostMapping("/upload")
public ResultVO upload(@RequestParam("file") MultipartFile file,
@RequestParam(value = "path", defaultValue = "/") String path) throws IOException {
FileSystem fileSystem = fileSystem();
Path hdfsPath = new Path(path, file.getOriginalFilename());
FSDataOutputStream outputStream = fileSystem.create(hdfsPath);
IOUtils.copy(file.getInputStream(), outputStream);
outputStream.hsync();
outputStream.close();
return ResultVO.success();
}
```
前端需要使用Vue的el-upload组件实现文件上传。以下是基本的前端代码:
```html
<template>
<div class="file-upload">
<el-upload :action="$axios.defaults.baseURL + '/file/upload'" :data="{ path: currentPath }">
<el-button size="small" type="primary">Upload File</el-button>
</el-upload>
</div>
</template>
```
4. 删除文件
可以使用Hadoop的FileSystem API来实现文件删除,将前端传递过来的文件在HDFS文件系统中删除。以下是基本的后端代码:
```java
@PostMapping("/delete")
public ResultVO delete(@RequestParam("path") String path) throws IOException {
FileSystem fileSystem = fileSystem();
Path hdfsPath = new Path(path);
boolean success = fileSystem.delete(hdfsPath, true);
return success ? ResultVO.success() : ResultVO.fail("Delete failed!");
}
```
前端需要使用Vue的el-popconfirm组件弹出确认框,确认要删除文件后再发送POST请求进行删除。以下是基本的前端代码:
```html
<template>
<div class="file-delete">
<el-popconfirm
title="Are you sure to delete this file?"
confirmButtonText="Yes"
cancelButtonText="No"
icon="el-icon-warning"
@confirm="handleDelete"
>
<el-button size="small" type="danger">Delete</el-button>
</el-popconfirm>
</div>
</template>
<script>
export default {
props: {
path: { type: String, required: true },
},
methods: {
async handleDelete() {
const response = await this.$axios.post("/file/delete", { path: this.path });
if (response.data.code === 0) {
this.$emit("delete-success");
} else {
this.$message.error(response.data.msg);
}
},
},
};
</script>
```
5. 下载文件
可以使用Hadoop的FileSystem API来实现文件下载,将前端传递过来的文件从HDFS文件系统中下载到本地。以下是基本的后端代码:
```java
@GetMapping("/download")
public void download(@RequestParam("path") String path, HttpServletResponse response) throws IOException {
FileSystem fileSystem = fileSystem();
Path hdfsPath = new Path(path);
FSDataInputStream inputStream = fileSystem.open(hdfsPath);
String fileName = hdfsPath.getName();
fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
IOUtils.copy(inputStream, response.getOutputStream());
inputStream.close();
}
```
前端需要使用Vue的a标签跳转到一个新的页面进行文件下载。以下是基本的前端代码:
```html
<template>
<div class="file-download">
<a :href="$axios.defaults.baseURL + '/file/download?path=' + path" target="_blank">
<el-button size="small" type="primary">Download</el-button>
</a>
</div>
</template>
```
6. 进入下一级
可以使用Vue的router实现进入下一级目录。在前端代码中,需要为文件夹类型的文件添加点击事件,然后使用router.push跳转到下一级页面。以下是基本的前端代码:
```html
<template>
<div class="file-list">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Size</th>
<th>Last Modified</th>
</tr>
</thead>
<tbody>
<tr v-for="fileInfo in pageData" :key="fileInfo.path">
<td>
<a v-if="fileInfo.isDirectory" @click="enterDirectory(fileInfo.path)">
<i class="fa fa-folder"></i> {{ fileInfo.name }}
</a>
<a v-else href="#" @click="downloadFile(fileInfo.path)">
<i class="fa fa-file"></i> {{ fileInfo.name }}
</a>
</td>
<td>{{ fileInfo.isDirectory ? 'Directory' : 'File' }}</td>
<td>{{ formatFileSize(fileInfo.length) }}</td>
<td>{{ formatDateTime(fileInfo.modificationTime) }}</td>
</tr>
</tbody>
</table>
<pagination :page-count="totalPage" :current-page="currentPage" @page-change="handlePageChange" />
</div>
</template>
<script>
export default {
methods: {
enterDirectory(path) {
this.$router.push({ path: "/fileList", query: { path } });
},
},
created() {
const path = this.$route.query.path || "/";
this.loadPageData(path, 10, 1);
},
watch: {
$route(to, from) {
const path = to.query.path || "/";
this.loadPageData(path, 10, 1);
},
},
};
</script>
```
7. 返回上一级
可以使用Vue的router实现返回上一级目录。在前端代码中,需要使用router.go(-1)方法返回上一级页面。以下是基本的前端代码:
```html
<template>
<div class="file-list-header">
<div>
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item @click="goBack">Home</el-breadcrumb-item>
<el-breadcrumb-item v-for="(item, index) in breadcrumb" :key="index">
{{ item.name }}
</el-breadcrumb-item>
</el-breadcrumb>
</div>
</div>
</template>
<script>
export default {
computed: {
breadcrumb() {
const path = this.$route.query.path || "/";
const pathArr = path.split("/").filter(item => item);
return pathArr.map((item, index) => ({
name: item,
path: "/" + pathArr.slice(0, index + 1).join("/"),
}));
},
},
methods: {
goBack() {
this.$router.go(-1);
},
},
};
</script>
```
以上是基本的实现步骤和前后端代码,可以根据实际需求进行调整和扩展。
阅读全文