主要實現的功能:
是實現文件列表顯示,包括文件夾和文件的列表顯示;
文件下載;
文件上傳;
(一)文件列表顯示
文件列表顯示,類似於樹形結構的文件夾列表顯示。
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項目中,。關於源碼,我會重新整理並進行上傳。