java实现系统文件管理
环境:jdk17+springboot+Vue+ElementUI
背景:公司所做的项目需要别的系统向我们服务器上传文件,当我们需要查看这些文件什么时候上传的、文件数据是怎样的,只能去机房,排查问题效率较低,做此页面,可快速查看上传的文件信息,且可下载到本地查看。为了生产安全,不支持修改及上传文件,如果有的朋友想做,可自行查找资料。
需求:实现系统文件的查询及下载。展示系统的文件信息,如文件名、文件大小、最后更新时间及权限等。
注意
:本篇文章是以window系统做的样例,不过一般服务器都是在linux系统,只需将前端的初始地址换成linux地址,一般格式为:/home/app。
效果图
直接上代码,前端代码:
<template>
<div>
<div>
<el-col :xl="4" :lg="5">
<el-input v-model="curPath" label-width='80px' size="small" type="text">当前位置:</el-input>
</el-col>
<el-button type="primary" size="small" @click="getParentData()" icon="el-icon-back">返回上级</el-button>
<el-button type="primary" size="small" @click="refresh()" icon="el-icon-refresh">刷新</el-button>
</div>
<el-table :data="fileList" v-loading="tableLoading">
<el-table-column label="名称" prop="fileName">
<!-- eslint-disable-next-line-->
<template slot-scope="scope">
<el-button type="text" v-if="!scope.row.fileType" @click="getSonData(scope.row)">{{
scope.row.fileName
}}
</el-button>
<span v-if="scope.row.fileType">{{ scope.row.fileName }}</span>
</template>
</el-table-column>
<el-table-column label="类型" align="center">
<!-- eslint-disable-next-line-->
<template slot-scope="scope">
<div>
{{ typeName(scope.row.fileType) }}
</div>
</template>
</el-table-column>
<el-table-column label="大小" prop="fileSize"></el-table-column>
<el-table-column label="更新时间" prop="lastModifiedDate"></el-table-column>
<el-table-column align="center" label="权限" width="120">
<!-- eslint-disable-next-line-->
<template slot-scope="scope">
<div>
{{ getAuthority(scope.row) }}
</div>
</template>
</el-table-column>
<el-table-column label="操作">
<!-- eslint-disable-next-line-->
<template slot-scope="scope">
<el-button size="mini" v-if="scope.row.fileType" type="text" @click="download(scope.row.path)">下载
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import axios from "axios";
export default {
name: 'App',
data() {
return {
curPath: "D:\\",
fileList: [],
tableLoading: false,
}
},
created() {
this.getData()
},
methods: {
getData: function () {
const vm = this
const params = {
path: this.curPath
}
axios({
method: 'get',
url: "/sysFile/getSysFiles",
params
}).then(res => {
const result = res.data
if (result && result.code === 200) {
this.fileList = result.data
console.log(this.fileList)
}
vm.tableLoading = false
})
},
getSonData(row) {
this.curPath = row.path
this.getData()
},
getParentData() {
if (this.curPath === '') {
this.$message({
type: 'warning',
message: '没有上级!'
})
return
}
// linux系统中,将 \\ 改为 / 即可
this.curPath = this.curPath.slice(0, this.curPath.lastIndexOf("\\"))
this.getData()
},
refresh() {
this.type = 0
this.getData()
},
download(path) {
const params = {
path: path
}
axios({
method: 'get',
url: "/sysFile/downloadFile",
responseType: 'blob',
params
}).then(res => {
// linux系统中,将 \\ 改为 / 即可
const fileName = path.slice(path.lastIndexOf("\\") + 1, path.length)
const blob = new Blob([res.data])
if ('download' in document.createElement('a')) {
// 非IE下载
console.log('非IE')
const elink = document.createElement('a')
elink.download = fileName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href)
// 释放URL 对象
document.body.removeChild(elink)
} else {
// IE10+下载
navigator.msSaveBlob(blob, fileName)
}
})
},
typeName(type) {
if (type) {
return "文件"
}
return "文件夹"
},
getAuthority(row) {
let authority = ''
if (row.canRead) {
authority = authority + 'r'
} else {
authority = authority + '-'
}
if (row.canWrite) {
authority = authority + 'w'
} else {
authority = authority + '-'
}
if (row.canExecute) {
authority = authority + 'x'
} else {
authority = authority + '-'
}
return authority
}
}
}
</script>
<style>
.el-header, .el-footer {
background-color: #B3C0D1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
text-align: center;
line-height: 200px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
line-height: 160px;
}
body > .el-container {
margin-bottom: 40px;
}
.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}
.el-container:nth-child(7) .el-aside {
line-height: 320px;
}
</style>
后端代码:
package org.wjg.onlinexml.controller;
import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.wjg.onlinexml.po.Result;
import org.wjg.onlinexml.po.SysFileDo;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
@RestController
public class SysFileController {
private static final SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@GetMapping("/getSysFiles")
public Result getSysFiles(@RequestParam String path) {
try {
File files = null;
if (!StringUtils.isEmpty(path)) {
files = new File(path);
} else {
return Result.builder().code(200).msg("路径为空").build();
}
if (!files.exists()) {
return Result.builder().code(200).msg("文件不存在").build();
}
List<SysFileDo> result = new ArrayList<>();
for (File file : files.listFiles()) {
SysFileDo sysFileDo = new SysFileDo();
//文件名
sysFileDo.setFileName(file.getName());
//是否为文件
sysFileDo.setFileType(file.isFile());
//文件大小,文件夹大小一般形式为0,不过可以自己遍历文件夹下的内容计算该文件夹的大小
sysFileDo.setFileSize(file.length() / 1024 + "KB");
//是否可执行
sysFileDo.setCanExecute(file.canExecute());
//是否可读
sysFileDo.setCanRead(file.canRead());
//是否可写(以上三种权限跟实际可能会有偏差的)
sysFileDo.setCanWrite(file.canWrite());
// 最后修改时间
sysFileDo.setLastModifiedDate(simple.format(new Date(file.lastModified())));
//最后修改时间的时间戳,方便排序
sysFileDo.setLastModified(file.lastModified());
//当前路径
sysFileDo.setPath(file.getAbsolutePath());
result.add(sysFileDo);
}
Collections.sort(result, Comparator.comparing(SysFileDo::getLastModified));
Collections.reverse(result);
return Result.builder().code(200).msg("查询成功").data(result).build();
} catch (Exception e) {
e.printStackTrace();
}
return Result.builder().build();
}
@RequestMapping("/downloadFile")
public ResponseEntity<byte[]> download(@RequestParam String path) throws IOException {
File file = new File(path);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentDispositionFormData("attachment", "");
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), httpHeaders, HttpStatus.CREATED);
}
}
实体类:
@Data
@NoArgsConstructor
public class SysFileDo {
private String fileName;
private boolean fileType;
private String fileSize;
private boolean canRead;
private boolean canExecute;
private boolean canWrite;
private String lastModifiedDate;
private long lastModified;
private String path;
}
package org.wjg.onlinexml.po;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
private int code;
private String msg;
private T data;
}
好了,主要的代码就这些。还有两个依赖:
<!-- 处理文件上传的 Java 库 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.5</version>
</dependency>
<!-- Apache 的开源工具库,包含了许多实用的文件操作、流操作相关的功能和工具类,比如文件读写、文件和目录的操作、流的处理和转换 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>