主要实现的功能:

是实现文件列表显示,包括文件夹和文件的列表显示;

文件下载;

文件上传;

(一)文件列表显示

文件列表显示,类似于树形结构的文件夹列表显示。

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请求的两种大类,一种是表单形式,另外一种就是非表单形式,常用于文件上传。其实文件上传还可以衍生出来很多,比如比较实用的断点续传功能,但由于本人刚入门不算太久,尝试过几次还没有能实现的案例,暂且不谈,后续肯定会进行补充。


(三)文件下载

可以参考另外一篇文章:;

另外如果结合本篇还可以更少行代码

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项目中,。关于源码,我会重新整理并进行上传。