主要实现的功能:
是实现文件列表显示,包括文件夹和文件的列表显示;
文件下载;
文件上传;
(一)文件列表显示
文件列表显示,类似于树形结构的文件夹列表显示。
1、如何实现?
实现方法:
private static List<FileInfo> getFileInfoList(String path) {
List<FileInfo> list = new LinkedList<>();
File file = new File(path);
if (file.isFile()) {
throw new RuntimeException("不是文件夹");
} else {
File[] lists = file.listFiles();
//循环
for (int i = 0; i < lists.length; i++) {
FileInfo fileInfo = new FileInfo();
File file_i = lists[i];
fileInfo.setName(file_i.getName());
fileInfo.setCapacity(file_i.length() + "");
fileInfo.setUpdateDate(new Date(file_i.lastModified()));
if (file_i.isFile()) {
fileInfo.setType("file");
} else {
fileInfo.setType("folder");
}
list.add(fileInfo);
}
return list;
}
}
其中FileInfo中定义了一些属性,主要包括:文件名name、文件大小capacity、修改时间updateDate、文件类型type:
public class FileInfo implements Serializable{
private String id;
private String name;
private String capacity;
private String type;
private Date updateDate;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCapacity() {
return capacity;
}
public void setCapacity(String capacity) {
this.capacity = capacity;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
}
参数path从请求中获取,这个path就是文件/文件夹所在的相对路径,在测试类中使用Request.getParameter(path)获得。
实现方法中可以看到,主要的逻辑就是,将目标path创建一个File对象,判断是文件还是文件夹,如果是文件夹,那就对文件夹下的文件/二级文件夹进行遍历,获取相对应的文件/二级文件夹信息,然后以列表的形式返回。
2、如果是POST的请求,后台如何在POST方法中返回json串?
众所周知,Servlet中,POST方法的返回形式是void,所以如何返回给前端json格式的字符串常常让新的同学们产生疑惑,这里提供一种方法:
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
String jsonStr = "{\"success\":\"true\"}";
PrintWriter out = null;
try {
out = response.getWriter();
out.write(jsonStr);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
3、测试类(包含跨域问题的后台设置)
public class GetListTest extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//跨域请求解决
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
//获取文件请求路径
String file_path = request.getParameter("file_path");
String path = "***";
if (file_path != null) {
path = "***" + file_path;
}
GetListClass getListClass = new GetListClass();
List<FileInfo> aa = GetListClass.getFileInfoList(path);
}
}
以上就是文件列表显示的主要部分介绍,源码链接(待补充);
(二)文件上传
1、如何实现?该部分代码注释非常详细,***处与上一节文件列表显示一样,服务器文件根目录,用户不可见。
public class FileUpload extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = request.getParameter("file_path");
System.out.println(path);
String savePath = "***";
if(path != null){
savePath = "***"+path;
}
//文件上传逻辑
File file = new File(savePath);
System.out.println(savePath);
//判断上传文件的保存目录是否存在
if (!file.exists() && !file.isDirectory()) {
System.out.println(savePath+"目录不存在,需要创建");
//创建目录
file.mkdir();
}
//消息提示
String message = "";
try{
//使用Apache文件上传组件处理文件上传步骤:
//1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
//解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//3、判断提交上来的数据是否是上传表单的数据
if(!ServletFileUpload.isMultipartContent(request)){
//按照传统方式获取数据
return;
}
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list){
//如果fileitem中封装的是普通输入项的数据
if(item.isFormField()){
String name = item.getFieldName();
//解决普通输入项的数据的中文乱码问题
String value = item.getString("UTF-8");
//value = new String(value.getBytes("iso8859-1"),"UTF-8");
System.out.println(name + "=" + value);
}else{//如果fileitem中封装的是上传文件
//得到上传的文件名称,
String filename = item.getName();
System.out.println(filename);
if(filename==null || filename.trim().equals("")){
continue;
}
//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
filename = filename.substring(filename.lastIndexOf("\\")+1);
//获取item中的上传文件的输入流
InputStream in = item.getInputStream();
//创建一个文件输出流
FileOutputStream out = new FileOutputStream(savePath + "\\" + filename);
//创建一个缓冲区
byte buffer[] = new byte[1024];
//判断输入流中的数据是否已经读完的标识
int len = 0;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while((len=in.read(buffer))>0){
//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
out.write(buffer, 0, len);
}
//关闭输入流
in.close();
//关闭输出流
out.close();
//删除处理文件上传时生成的临时文件
item.delete();
message = "文件上传成功!";
}
}
}catch (Exception e) {
message= "文件上传失败!,请重新上传";
e.printStackTrace();
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
String jsonStr = "{\"message\":\"" + message + "\"}";
PrintWriter out = null;
try {
out = response.getWriter();
out.write(jsonStr);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
上传功能还有很多种方式,但大多都是需要commons-fileupload-1.3.3.jar、commons-io-2.4.jar这两个个包的,其中包含丰富的功能。文件上传的请求方式比较特殊,Servlet请求的两种大类,一种是表单形式,另外一种就是非表单形式,常用于文件上传。其实文件上传还可以衍生出来很多,比如比较实用的断点续传功能,但由于本人刚入门不算太久,尝试过几次还没有能实现的案例,暂且不谈,后续肯定会进行补充。
(三)文件下载
可以参考另外一篇文章:http://blog.csdn.net/adelaide_guo/article/details/77757132;
另外如果结合本篇还可以更少行代码
String file_path = request.getParameter("file_path");
String path = "E:\\工作文件\\开发文档内容\\";
if (file_path != null) {
path = "E:\\工作文件\\开发文档内容\\" + file_path;
}
InputStream inputStream = null;
ServletOutputStream out = null;
try {
File file = new File(path);
String odexName = file.getName();
int fSize = Integer.parseInt(String.valueOf(file.length()));
response.setCharacterEncoding("utf-8");
response.setContentType("application/x-download");
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Content-Length", String.valueOf(fSize));
response.setHeader("Content-Disposition", "attachment;fileName=" + odexName);
inputStream = new FileInputStream(path);
long pos = 0;
if (null != request.getHeader("Range")) {
// 断点续传
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
try {
pos = Long.parseLong(request.getHeader("Range").replaceAll("bytes=", "").replaceAll("-", ""));
} catch (NumberFormatException e) {
pos = 0;
}
}
out = response.getOutputStream();
String contentRange = new StringBuffer("bytes ").append(pos + "").append("-").append((fSize - 1) + "").append("/").append(fSize + "").toString();
response.setHeader("Content-Range", contentRange);
inputStream.skip(pos);
byte[] buffer = new byte[1024 * 1000];
int length = 0;
while ((length = inputStream.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, length);
Thread.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != out) out.flush();
if (null != out) out.close();
if (null != inputStream) inputStream.close();
} catch (IOException e) {
}
}
这样的断点续传可以在浏览器中进行,通常浏览器自带的下载插件都可以实现断点下载,但是浏览器关闭后,下载内容删除,想要全方位实现断点下载功能,目前我能做到的只有起一个客户端,也就是上面那篇文章当中那样,但是有点过于繁琐,也不现实在一个web项目中,。关于源码,我会重新整理并进行上传。