import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.List;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.FileUploadException;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
/**
* 提供和Servlet有关的一系列工具方法(jdk8)
* @author 彭锋
* @2018年6月6日 下午2:41:30
*/
public final class MyServletUtils {
/**
* 解析文件上传的表单,并返回解析结果
* @param req
* @return
*/
public static final Map<String,List<FileItem>> parseMultipartParam(HttpServletRequest req){
//判断是否是文件上传的form
boolean b = ServletFileUpload.isMultipartContent(req);
if(b) {
try {
//是文件上传的表单提交
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置文件上传使用的缓存
factory.setSizeThreshold(1024*1024);
//创建ServletFileUpload对象
ServletFileUpload upload = new ServletFileUpload(factory);
//解析请求,获取封装了上传的表单数据的Map集合并返回
return upload.parseParameterMap(req);
} catch (FileUploadException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 根据name获取文件上传的表单提交过来的一个值
* @param map
* @param name
* @return
*/
public static final String getMultipartParam(Map<String,List<FileItem>> map,String name) {
String[] values = getMultipartParams(map,name);
if(values != null && values.length > 0) {
return values[0];
}
return null;
}
/**
* 根据name获取文件上传的表单提交过来的多个值
* @param map
* @param name
* @return
*/
public static final String[] getMultipartParams(Map<String,List<FileItem>> map,String name) {
String[] values = null;
List<FileItem> list = map.get(name);
if(list != null && !list.isEmpty()) {
values = new String[list.size()];
try {
for (int i = 0; i < values.length; i++) {
FileItem item = list.get(i);
values[i] = item.getString("utf-8");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return values;
}
/**
* 根据指定的name,获取文件上传表单中提交过来的一个FileItem对象
* @param map
* @param name
* @return
*/
public static final FileItem getMultipartFile(Map<String,List<FileItem>> map,String name) {
FileItem[] values = getMultipartFiles(map,name);
if(values != null && values.length > 0) {
return values[0];
}
return null;
}
/**
* 根据指定的name,获取文件上传表单中提交过来的FileItem数组
* @param map
* @param name
* @return
*/
public static final FileItem[] getMultipartFiles(Map<String,List<FileItem>> map,String name) {
FileItem[] values = null;
List<FileItem> list = map.get(name);
if(list != null && !list.isEmpty()) {
values = list.toArray(new FileItem[list.size()]);
}
return values;
}
/**
* 根据文件名的哈希值,使用按位与和移位运算的方式,生成n级目录
* @param parentPath 要生成的文件夹的父目录
* @param fileName 文件名
* @param n 要生成的文件目录的层数,最小1,最高8
* @return
*/
public static final String createDirs(String parentPath,String fileName,int n) {
if(fileName != null && fileName.trim().length() > 0) {
String dirPath = "/";
//根据文件名,获取哈希码
int code = fileName.hashCode();
//判断n的值,最低不能小于1,最多不能大于8
if(n <= 0) {
n = 1;
}else if(n > 8) {
n = 8;
}
//根据要生成的文件夹的级数,生成对应的文件夹的路径
for(int i = 0; i < n; i++) {
code = code >>> 4*i;
dirPath = dirPath+ (code & 15) +"/";
}
File parentDir = new File(parentPath);
if(!parentDir.exists()) {
throw new RuntimeException("指定的父目录不存在!");
}
File dir = new File(new File(parentPath),dirPath);
if(!dir.exists()) {
dir.mkdirs();
}
return dirPath;
}
throw new NullPointerException("文件名不能为空!");
}
/**
* 删除Cookie
* @param resp 响应对象
* @param cookie 要删除的Cookie
*/
public static final void deleteCookie(HttpServletResponse resp,Cookie cookie) {
if(cookie != null) {
cookie.setValue("");
cookie.setMaxAge(0);
resp.addCookie(cookie);
}
}
/**
* 根据指定的名字,从请求中查找cookie
* @param req
* @param name
* @return
*/
public static final Cookie getCookie(HttpServletRequest req,String name) {
Cookie[] cookies = req.getCookies();
if(cookies != null && cookies.length > 0) {
for (Cookie cookie : cookies) {
if(cookie.getName().equals(name)) {
return cookie;
}
}
}
return null;
}
/**
* 判断从页面提交的数据和session中相同名称的数据是否相等(可用于判断验证码等)
* @param req 请求对象
* @param keyName 请求和session中保存的相同的键名
* @return
*/
public static final boolean isEqual(HttpServletRequest req,String keyName) {
String data = req.getParameter(keyName);
if(data == null) {
return false;
}else {
return data.equals(req.getSession().getAttribute(keyName));
}
}
/**
* 针对文件下载的请求,对响应进行处理,并返回响应给浏览器的字节输出流
* @param req 请求对象
* @param resp 响应对象
* @param fileName 返回给浏览器显示用的下载的文件名
* @return
* @throws IOException
*/
public static final OutputStream downloadProcessing(HttpServletRequest req, HttpServletResponse resp,String fileName) throws IOException {
//设置返回给浏览器的数据的类型
resp.setContentType(req.getServletContext().getMimeType(fileName));
/*
* 处理返回给浏览器的文件名,避免出现中文乱码
* 需要对下载的文件名进行编码:保证浏览器端可以正常的显示数据
* 这里需要对setHeader中的value值进行编码,这里不同的浏览器采用的编码形式不一样。
* IE、Chrome 等他们可以使用Java中提供的EncodeURL类进行编码。
* 而Firefox它内部采用的Base64编码,我们需要判断用户当前使用的是什么浏览器,然后确定对应的编码算法
* 在用户发出请求的时候,在请求头中携带了当前浏览器的信息 user-agent
*/
String agent = req.getHeader("user-agent");
//判断用户使用的浏览器
if( agent!=null && agent.contains("Firefox") ){
/*
* 判断成立,说明用户使用的是火狐浏览器 ,需要对文件名进行base64编码,然后进行如下处理
*/
//获取base64编码对象
Encoder encoder = Base64.getEncoder();
//对文件名进行base64编码
String base64 = encoder.encodeToString(fileName.getBytes("utf-8"));
//对编码过后的文件名进行如下处理
fileName = "=?utf-8?B?"+ base64 +"?=";
}else{
//使用的IE ,Chrome 等浏览器
fileName = URLEncoder.encode(fileName, "utf-8");
}
/*
* 通过设置响应头,告诉浏览器以附件下载的方式处理收到的数据
* setHeader 设置响应的头信息:
* key :Content-Disposition
* value: attachment 告诉浏览器当前的 数据需要以附件下载的方式打开
* filename=浏览器显示的下载的文件名
* */
resp.setHeader("Content-Disposition", "attachment;filename=" + fileName);
return resp.getOutputStream();
}
}