servlet實現上傳下載
文件上傳頁面三要素
- 提供form表單,method必須是post
- form表單的enctype必須是multipart/form-data
- 提供 input type=“file” 類型輸入
jar包:
commons-fileupload.jar
commons-io.jar
文件上傳:
主流程類:
package com.booy;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
//文件上傳
@WebServlet(name = "uploadServlet",value = "/uploadServlet")
//文件註解,註解必須寫,文件大小限制,不寫參數默認不限制大小
@MultipartConfig(maxFileSize = 1024*1024*10,maxRequestSize = 1024*1024*100)
public class uploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//設置編碼
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//輸出流
PrintWriter out = response.getWriter();
//接收文件
Collection<Part> parts = request.getParts();
//文件保存的位置
String basePath = this.getServletContext().getRealPath("/WEB-INF/upload");
File dir = new File(basePath);
//如果沒有文件夾就創建
if(!dir.exists()){
dir.mkdirs();
}
if(parts!=null){
for (Part part:parts){
//通過文件名,判斷是文件還是普通項,普通項沒有文件名
String fileName = part.getSubmittedFileName();
if(fileName==null){
//不是文件就獲取用戶名
String name = part.getName();
String value = request.getParameter(name);
System.out.println(name+"-->"+value);
}else{
System.out.println("文件名是:"+fileName);
if(fileName==""){
continue;
}
//通過uuid拼接的新文件名
String newFileName = UploadUtils.createNewFileName(fileName);
//新文件夾名
String newdirname = UploadUtils.createNewPath(basePath, fileName);
//保存文件
part.write(newdirname+"/"+newFileName);
//清理緩存
part.delete();
//響應內容
out.write("<h2>上傳成功:</h2>"+fileName+"<br>");
}
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
工具類:UploadUtils
文件上傳用到工具類中的文件名和文件夾重新生成方法,文件下載用到了文件查詢方法
package com.booy;
import java.io.File;
import java.util.HashMap;
import java.util.UUID;
//工具操作類
public class UploadUtils {
//文件重新生成文件名,通過uuid
public static String createNewFileName(String oldFilename){
//生成UUID並通過replace方法去掉“-”
String uuid = UUID.randomUUID().toString().replace("-","");
//新文件名爲uuid+原文件名
String newFileName=uuid+"_"+oldFilename;
return newFileName;
}
//文件夾重命名
public static String createNewPath(String basePath,String oldfileName){
//獲取舊文件名的hashCode
int hashCode = oldfileName.hashCode();
//舊文件名的hashCode取後四位
int dir1 = hashCode&0xf;
//舊文件名的hashCode取第二個後四位
int dir2 = (hashCode&0xf0)>>>4;
//拼接新的文件路徑
String newPath = basePath+"/"+dir1+"/"+dir2;
//如果沒有就創建文件夾
File dir = new File(newPath);
if(!dir.exists()){
dir.mkdirs();
}
return newPath;
}
//查找文件夾下面的文件放於Map集合中
public static void listFiles(File dir, HashMap<String, String> map){
//獲取文件對象列表
File[] files = dir.listFiles();
//判斷文件列表不爲空
if(files!=null){
//遍歷文件列表
for(File file:files){
//如果是文件夾繼續遍歷
if(file.isDirectory()){
listFiles(file,map);
}else{
//獲取文件的帶uuid的名稱
String uuidfilename = file.getName();
//indexOf拆分,截取原來的文件名
String filename = uuidfilename.substring(uuidfilename.indexOf("_")+1);
//存放Map中
map.put(uuidfilename,filename);
}
}
}
}
}
jsp頁面上傳展示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上傳</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/uploadServlet" enctype="multipart/form-data" method="post">
上傳用戶:<input type="text" name="username"><br/>
上傳文件1:<input type="file" name="file1"><br/>
上傳文件2:<input type="file" name="file2"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
文件下載:
主流程類
package com.booy;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
@WebServlet(name = "ListFileServlet", value = "/ListFile")
public class ListFileServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//定義集合遍歷文件
HashMap<String, String> hashMap = new HashMap<>();
//獲取文件路徑
String basePath = this.getServletContext().getRealPath("/WEB-INF/upload");
//查找文件
UploadUtils.listFiles(new File(basePath),hashMap);
//把文件寫入域中
request.setAttribute("maps",hashMap);
//轉發到指定頁面處理
request.getRequestDispatcher("/list.jsp").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
下載功能類:
package com.booy;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
//文件下載
@WebServlet(name = "DownServlet",value ="/down")
public class DownServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//設置字符編碼
request.setCharacterEncoding("utf-8");
//獲取帶UUID的文件名
String uuidfilename = request.getParameter("filename");
//設置文件夾基本位置
String basePath = this.getServletContext().getRealPath("/WEB-INF/upload");
//如果帶UUID的文件名不爲空,並且去掉左右空格的長度不爲0才進行下面操作
if(uuidfilename!=null&&uuidfilename.trim().length()!=0){
//_爲分隔符截取出不帶UUID的文件名
//uuidfilename.substring(0,uuidfilename.indexOf("_"));截取_前面的
String filename = uuidfilename.substring(uuidfilename.indexOf("_") + 1);
//獲取新的文件夾路徑
String newPath = UploadUtils.createNewPath(basePath, filename);
//創建file
File file = new File(newPath+"/"+uuidfilename);
if(file.exists()){
ServletOutputStream os = response.getOutputStream();
//響應頭設置下載
response.setHeader("content-disposition","attachmen;filename="+ URLEncoder.encode(filename,"utf-8"));
FileInputStream fis = new FileInputStream(file);
byte[] bytes = new byte[1024*4];
int len = -1;
while ((len=fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
}else{
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("文件已刪除");
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
jsp展示頁
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>文件下載</title>
</head>
<body>
<h2>下載列表</h2>
<c:forEach var="entry" items="${maps}">
${entry.value} <a href="${pageContext.request.contextPath}/down?filename=${entry.key}">下載</a>
</c:forEach>
</body>
</html>
過濾器
Filter也稱之爲過濾器,它是Servlet技術中最激動人心的技術,WEB開發人員通過Filter技術,對web服務器管理的所有web資源:例如Jsp, Servlet, 靜態圖片文件或靜態html文件等進行攔截,從而實現一些特殊的功能。例如實現URL級別的權限訪問控制、過濾敏感詞彙、壓縮響應信息等一些高級功能。
Servlet API中提供了一個Filter接口,開發web應用時,如果編寫的Java類實現了這個接口,則把這個java類稱之爲過濾器Filter。通過Filter技術,開發人員可以實現用戶在訪問某個目標資源之前,對訪問的請求和響應進行攔截。
編寫過濾器
1、編寫java類實現Filter接口
2、重寫doFilter方法
3、設置攔截的url
註解式配置
在自定義的Filter類上使用註解@WebFilter(“/*”)
過濾器的攔截匹配路徑通常有三種形式:
(1)精確攔截地址匹配 ,比如/index.jsp
(2)後綴攔截地址匹配,比如*.jsp、.html、.jpg
(3)通配符攔截匹配/*,表示攔截所有、注意過濾器不能使用/匹配。
過濾器鏈
通常客戶端對服務器請求之後,服務器調用Servlet之前會執行一組過濾器(多個過濾器),那麼這組過濾器就稱爲一條過濾器鏈。
每個過濾器實現某個特定的功能,當第一個Filter的doFilter方法被調用時,web服務器會創建一個代表Filter鏈的FilterChain對象傳遞給該方法。在doFilter方法中,開發人員如果調用了FilterChain對象的doFilter方法,則web服務器會檢查FilterChain對象中是否還有filter,如果有,則調用第2個filter,如果沒有,則調用目標資源。
過濾器的優先級
在一個web應用中,可以開發編寫多個Filter,這些Filter組合起來稱之爲一個Filter鏈。這些過濾器的執行順序由filter-mapping的順序決定,前面filter-mapping優先級高於後面的。
注意:
(1)如果爲註解的話,是按照類名的字符串順序進行起作用的
(2)如果web.xml,按照 filter-mapping註冊順序,從上往下
(3)web.xml配置高於註解方式
(4)如果註解和web.xml同時配置,會創建多個過濾器對象,造成過濾多次。
過濾器實現自動登錄:
登錄頁面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登錄</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/LoginServlet" method="post">
登錄名:<input type="text" name="username" placeholder="請輸入用戶名">
<br>
密 碼:<input type="text" name="password" placeholder="請輸入密碼">
<br>
自動登錄:<input type="checkbox" name="auto">
<input type="submit" value="提交">
</form>
</body>
</html>
主頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
我是主頁,welcom home ${username}!
</body>
</html>
登錄Servlet:
package com.booy;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Base64;
@WebServlet(name = "LoginServlet",value = "/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
String auto = request.getParameter("auto");
if(username.equals("booy")&&password.equals("123456")){
System.out.println("登錄成功");
request.getSession().setAttribute("username",username);
if(auto!=null){
String userInfo = username+"#"+password;
String base64Info = Base64.getEncoder().encodeToString(userInfo.getBytes());
Cookie userInfoCookie = new Cookie("userInfo", base64Info);
userInfoCookie.setMaxAge(60*60*24*7);
userInfoCookie.setPath("/");
userInfoCookie.setHttpOnly(true);
response.addCookie(userInfoCookie);
System.out.println("自動登錄Cookie創建了");
}
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
自動登錄Filter:
package com.booy;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Base64;
@WebFilter(filterName = "AutoFilter",value = "/index.jsp")
public class AutoFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//強轉
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
Object username = request.getSession().getAttribute("username");
if(username!=null){
chain.doFilter(req, resp);
}
//獲取Cookie
Cookie[] cookies = request.getCookies();
if(cookies!=null){
for(Cookie cookie:cookies){
if(cookie.getName().equals("userInfo")){
String base64Info = cookie.getValue();
byte[] decode = Base64.getDecoder().decode(base64Info);
String userInfo = new String(decode);
System.out.println(userInfo);
String[] userInfos = userInfo.split("#");
if(userInfos[0].equals("booy")&&userInfos[1].equals("123456")){
System.out.println("用戶自動登錄成功");
request.getSession().setAttribute("username",userInfos[0]);
}else{
Cookie cookie1 = new Cookie("userInfo","");
cookie1.setMaxAge(0);
cookie1.setPath("/");
response.addCookie(cookie1);
}
}
}
}
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}