步骤大概分为几步:
- 读取并在前端显示服务器的文件
- 从前端发出请求下载文件
- 到后端获取下载文件的流并保存
demo是从网上找并且修改的,项目日期比较急。改的有点粗糙,有几个点可以优化下
下面逐步讲解
1、首先应该发送请求到后端读取本地文件,无非就是ajax略
2、后端接收请求并扫秒目标目录里及其子目录文件,改的比较丑陋。大致思想是遇见文件插入,再读取遇见里面的文件,这么一层一层下去。
public static List<FileInfo> getLandBaseFileList(String path) {
/*"/projects/smart_gateway/Customer/"
* */
List<FileInfo> fileInfos = new ArrayList<>();
List<FileInfo> fileInfos2 = new ArrayList<>();
File baseFile = new File(path);
File[] files = baseFile.listFiles();
//TODO 如果是文件在这里插入,如果是文件夹执行后面的操作
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()){
FileInfo cursor = new FileInfo();
cursor.setPath(files[i].getPath());
cursor.setFileName(files[i].getName());
num=num+1;
cursor.setNum(num);
fileInfos.add(cursor);
}
else {
String path1=files[i].getPath();
fileInfos2= FileService.getLandBaseFileList2(path1,fileInfos);
fileInfos=fileInfos2;
}
}
System.out.println(fileInfos);
num=0;
return fileInfos;
}
public static List<FileInfo> getLandBaseFileList2(String path,List<FileInfo> fileInfos) {
/*"/projects/smart_gateway/Customer/"
//TODO 递归获得所有文件夹
* */
List<FileInfo> fileInfos2 = new ArrayList<>();
File baseFile = new File(path);
File[] files = baseFile.listFiles();
if (files!=null)
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()){
FileInfo cursor = new FileInfo();
cursor.setPath(files[i].getPath());
cursor.setFileName(files[i].getName());
num=num+1;
cursor.setNum(num);
fileInfos.add(cursor);
}
else {
String path1=files[i].getPath();
fileInfos2= FileService.getLandBaseFileList2(path1,fileInfos);
fileInfos=fileInfos2;
}
}
System.out.println(fileInfos);
return fileInfos;
}
3、前端展示
function setTbody (arr) {
var html = '';
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
var path =item.path;
/* download item.path*/
var str=path.split("\\");
var savpath="";
for(var j=2 ;j<str.length; j++)
{
savpath=savpath+"\\"+str[j];
}
html += '<tr><td>' + item.num + '</td><td>' + savpath + '</td><td>' + '<a href="/download?downFilePath=' + encodeURI(path) + '"' + '>' + '下载 </a>' + '</td></tr>';
}
$('.tbody').append(html);
}
这里没有后端分页,以后文件量大的话需要修改一下
4、前端发送请求到后端下载
ajax略,无非就是拿到一个文件名
// 判断文件是否存在
File file = new File(filePath);
log.info("DOWNLOAD PATH:" + filePath);
if (!file.exists() || file.isDirectory()) {
log.info("FILE DOES NOT EXIST!");
return "failure";
}
// 自定义文件名
String[] split = filePath.split("/");
String filename = split[split.length - 1];
System.out.println(filename);
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
InputStream in = null;
BufferedInputStream bis = null;
OutputStream out = null;
BufferedOutputStream bos = null;
try {
in = new FileInputStream(filePath);
bis = new BufferedInputStream(in);
byte[] data = new byte[1024];
int bytes = 0;
out = response.getOutputStream();
bos = new BufferedOutputStream(out);
while ((bytes = bis.read(data, 0, data.length)) != -1) {
bos.write(data, 0, bytes);
}
bos.flush();
} catch (Exception e) {
log.error("THE REQUEST FAILED:" + e.getMessage(), e);
return "failure";
} finally {
try {
if (bos != null) {
bos.close();
}
if (out != null) {
out.close();
}
if (bis != null) {
bis.close();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return "success";
}
然后就完成了,发现是直接下载到指定的文件名那里,相对路径会是浏览器下载的路径+指定文件名,绝对路径就是绝对路径那。于是我想着能不能弹出一个对话框那样指定下载路径,一开始想着改改请求头就行了。找了半天没找到,后来一想请求头也确实做不到啊 - -,通过请求头直能下载到指定的路径(后端设置请求头时完成),要想指定路径还是得通过js,于是想到了file-input标签,读取本地路径就可以了。