SSM框架分页展示HDFS文件列表,返回上一级,进入下一级,上传文件,删除文件,下载文件前后端代码
时间: 2023-06-14 17:03:46 浏览: 236
基于SSM框架,前后端分离的文件云平台项目+源代码+文档说明
前端代码:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HDFS文件管理系统</title>
<style>
body {
font-size: 14px;
font-family: "Microsoft YaHei";
}
.container {
margin-top: 30px;
}
.table {
border-collapse: collapse;
border: 1px solid #ccc;
margin-bottom: 30px;
}
.table th, .table td {
border: 1px solid #ccc;
padding: 5px;
}
.table th {
background-color: #f5f5f5;
font-weight: bold;
text-align: center;
}
.table td {
text-align: left;
}
.table td a {
text-decoration: none;
}
.table td a:hover {
text-decoration: underline;
}
.pagination {
margin-top: 20px;
text-align: center;
}
.pagination a, .pagination span {
display: inline-block;
padding: 5px;
margin: 0 3px;
border: 1px solid #ccc;
background-color: #fff;
color: #333;
border-radius: 3px;
cursor: pointer;
text-decoration: none;
}
.pagination a:hover {
background-color: #f5f5f5;
}
.pagination .active {
background-color: #007bff;
color: #fff;
}
.pagination .disabled {
background-color: #f5f5f5;
color: #ccc;
cursor: not-allowed;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input[type=text], .form-group input[type=file] {
width: 100%;
padding: 5px;
border: 1px solid #ccc;
border-radius: 3px;
}
.form-group button {
margin-top: 10px;
padding: 5px 10px;
border: none;
background-color: #007bff;
color: #fff;
border-radius: 3px;
cursor: pointer;
}
.form-group button:hover {
background-color: #0069d9;
}
</style>
</head>
<body>
<div class="container">
<h1>HDFS文件管理系统</h1>
<hr>
<table class="table">
<thead>
<tr>
<th>文件名</th>
<th>大小</th>
<th>修改时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="file in files">
<td>
<a v-if="file.isDirectory" @click="goToDirectory(file.path)">{{ file.name }}</a>
<a v-else>{{ file.name }}</a>
</td>
<td>{{ file.size }}</td>
<td>{{ file.modifiedTime }}</td>
<td>
<a v-if="!file.isDirectory" :href="downloadUrl(file.path)">下载</a>
<a v-if="!file.isDirectory" @click="deleteFile(file.path)">删除</a>
</td>
</tr>
</tbody>
</table>
<div class="pagination">
<a v-if="currentPage > 1" @click="goToPage(currentPage - 1)">上一页</a>
<a v-for="page in pages" :class="{ active: currentPage === page }" @click="goToPage(page)">{{ page }}</a>
<a v-if="currentPage < totalPages" @click="goToPage(currentPage + 1)">下一页</a>
</div>
<div class="form-group">
<label>上传文件</label>
<input type="file" @change="uploadFile">
</div>
<div class="form-group">
<button @click="goToParentDirectory">返回上一级</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
files: [], // 文件列表
currentPage: 1, // 当前页码
pageSize: 10, // 每页显示的文件数
totalFiles: 0, // 总文件数
totalPages: 0, // 总页数
pages: [] // 页码列表
},
mounted() {
// 初始化页面,显示 / 目录下的文件列表
this.getFiles('/');
},
methods: {
// 获取文件列表
getFiles(path) {
axios.get('/list', {
params: {
path: path,
currentPage: this.currentPage,
pageSize: this.pageSize
}
}).then(response => {
this.files = response.data.files;
this.totalFiles = response.data.totalFiles;
this.totalPages = Math.ceil(this.totalFiles / this.pageSize);
this.pages = [];
for (let i = 1; i <= this.totalPages; i++) {
this.pages.push(i);
}
}).catch(error => {
console.log(error);
});
},
// 跳转到指定页码
goToPage(page) {
if (page >= 1 && page <= this.totalPages) {
this.currentPage = page;
this.getFiles(this.currentPath);
}
},
// 进入目录
goToDirectory(path) {
this.currentPath = path;
this.currentPage = 1;
this.getFiles(path);
},
// 返回上一级目录
goToParentDirectory() {
if (this.currentPath !== '/') {
let index = this.currentPath.lastIndexOf('/');
let parentPath = this.currentPath.substring(0, index);
this.goToDirectory(parentPath);
}
},
// 上传文件
uploadFile(event) {
let formData = new FormData();
formData.append('file', event.target.files[0]);
formData.append('path', this.currentPath);
axios.post('/upload', formData).then(response => {
this.getFiles(this.currentPath);
}).catch(error => {
console.log(error);
});
},
// 删除文件
deleteFile(path) {
if (confirm('确定删除文件吗?')) {
axios.delete('/delete', {
params: {
path: path
}
}).then(response => {
this.getFiles(this.currentPath);
}).catch(error => {
console.log(error);
});
}
},
// 下载文件
downloadUrl(path) {
return '/download?path=' + encodeURIComponent(path);
}
},
computed: {
currentPath() {
return this.files.length > 0 ? this.files[0].path : '/';
}
}
});
</script>
</body>
</html>
```
后端代码:
```java
@Controller
public class HdfsController {
private static final int PAGE_SIZE = 10; // 每页显示的文件数
@Autowired
private FileSystem fileSystem;
/**
* 列出指定路径下的文件列表
*/
@GetMapping("/list")
@ResponseBody
public Map<String, Object> listFiles(
@RequestParam("path") String path,
@RequestParam("currentPage") int currentPage) throws IOException {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!fileSystem.exists(new Path(path))) {
throw new FileNotFoundException("File not found: " + path);
}
FileStatus[] fileStatuses = fileSystem.listStatus(new Path(path));
int startIndex = (currentPage - 1) * PAGE_SIZE;
int endIndex = Math.min(startIndex + PAGE_SIZE, fileStatuses.length);
List<Map<String, Object>> files = new ArrayList<>();
for (int i = startIndex; i < endIndex; i++) {
Map<String, Object> file = new HashMap<>();
file.put("name", fileStatuses[i].getPath().getName());
file.put("path", fileStatuses[i].getPath().toString());
file.put("isDirectory", fileStatuses[i].isDirectory());
file.put("size", fileStatuses[i].isDirectory() ? "" : FileUtils.byteCountToDisplaySize(fileStatuses[i].getLen()));
file.put("modifiedTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(fileStatuses[i].getModificationTime())));
files.add(file);
}
Map<String, Object> result = new HashMap<>();
result.put("files", files);
result.put("totalFiles", fileStatuses.length);
return result;
}
/**
* 上传文件
*/
@PostMapping("/upload")
@ResponseBody
public String uploadFile(@RequestParam("file") MultipartFile file,
@RequestParam("path") String path) throws IOException {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!fileSystem.exists(new Path(path))) {
throw new FileNotFoundException("File not found: " + path);
}
Path dstPath = new Path(path + "/" + file.getOriginalFilename());
FSDataOutputStream outputStream = fileSystem.create(dstPath);
IOUtils.copy(file.getInputStream(), outputStream);
IOUtils.closeQuietly(outputStream);
return "success";
}
/**
* 删除文件
*/
@DeleteMapping("/delete")
@ResponseBody
public String deleteFile(@RequestParam("path") String path) throws IOException {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!fileSystem.exists(new Path(path))) {
throw new FileNotFoundException("File not found: " + path);
}
fileSystem.delete(new Path(path), true);
return "success";
}
/**
* 下载文件
*/
@GetMapping("/download")
public void downloadFile(@RequestParam("path") String path, HttpServletResponse response) throws IOException {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!fileSystem.exists(new Path(path))) {
throw new FileNotFoundException("File not found: " + path);
}
FSDataInputStream inputStream = fileSystem.open(new Path(path));
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(new Path(path).getName(), "UTF-8"));
IOUtils.copy(inputStream, response.getOutputStream());
IOUtils.closeQuietly(inputStream);
}
}
```
以上代码是基于 Spring MVC 框架实现的,使用了 Vue.js 实现前端交互效果。其中,`listFiles` 方法用于列出指定路径下的文件列表,支持分页展示;`uploadFile` 方法用于上传文件;`deleteFile` 方法用于删除文件;`downloadFile` 方法用于下载文件。
阅读全文