文件管理總結(文件列表、文件上傳/下載)

主要實現的功能:

是實現文件列表顯示,包括文件夾和文件的列表顯示;

文件下載;

文件上傳;

(一)文件列表顯示

文件列表顯示,類似於樹形結構的文件夾列表顯示。

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項目中,。關於源碼,我會重新整理並進行上傳。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章