文件的上传
1.1文件上传的三要素
- 提供form表单,提交方式必须是“post”。
- form表单的enctype必须是multipart/form-data
- 提供input type="file"类型的输入
1.2实现文件的上传
新建表单:
<form action="${pageContext.request.contextPath}/upload"
method="post" enctype="multipart/form-data"/>
用户名:<input type="text" name="username"/><br>
文件1 : <input type="file" name="file1"/><br>
文件2:<input type="file" name="file2"/><br>
<input type="submit" value="提交文件"/><br>
</form>
为了防止文件重名覆盖, 必须先为上传文件产生一个的文件名
新建产生随机文件名的工具类
public class UploadUtils {
//为每一个上传的文件生成一个唯一的文件id
//重名容易发生覆盖
public static String newFlieName(String filename) {
return UUID.randomUUID().toString().replaceAll("-", "") + "_" + filename;
// UUID.randomUUID().toString()产生一个随机字符名
//replaceAll("-", "") + "_" + filename把随机生成的id中的下划线替换成空格再加上原文件真实名字
}
public static void main(String[] args) {
System.out.println(newFlieName("123.jpg"));
}
}
创建uploadservlet
@MultipartConfig(maxFileSize = 1024 * 1024 * 100, maxRequestSize = 1024 * 1024 * 200)
@WebServlet(name = "UploadServlet", value = "/upload")
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//文件上传的实现步骤
//获取文件上传的路径
//为了服务器安全,上传的文件应该保存在用户无法直接访问的目录下 比如WEB-INF下
String realPath = request.getServletContext().getRealPath("WEB-INF/upload");
File file = new File(realPath);
if (!file.exists()) {//如果upload不存在 直接创建
file.mkdirs();//创建文件夹
}
Collection<Part> parts = request.getParts();
System.out.println(parts.size());
for (Part part : parts) {
//2.在part可以获得当前上传的是文件还是普通表单
String filename = part.getSubmittedFileName();
if (filename != null) {
//通过工具类哪一个唯一的文件随机名称
String newFlieName = UploadUtils.newFlieName(filename);
//文件----->上传(路径+文件名)
part.write(realPath + File.separator + newFlieName);
part.delete();//清除临时缓存区
} else {
//打印或者后续改成上传数据库 调用service层
String name = part.getName();
String parameter = request.getParameter(name);
//
System.out.println(parameter);
}
}
}
}
1.3文件上传页面展示
控制台输出和在服务器端生成upload文件夹
打印的是multipart的大小的用户名
此时上传相同文件不会覆盖。
1.4 文件上传细节优化
为防止一个目录下面出现人太多文件,使用hash 算法打散存储
在工具类中再添加方法
//2.为了防止一个目录下文件过多 采用hash算法打散
public static String newFliePath(String basepath, String filename) {
//1.拿到文件名称的hash码
int hashCode = filename.hashCode();
//2.哈希码进行&运算,生成二级目录
int path2 = hashCode & 15;
//3.三级目录
int path3 = (hashCode >> 4) & 15;//hash码右移四位 再与运算生成三级目录
//4.将一集目录+二级+三级 生成一个新的完整的目录
String newPath = basepath + File.separator + path2 + File.separator + path3;
File file = new File(newPath);
if (!file.exists()) {
file.mkdirs();//文件不存在则创建
}
return newPath;
}
uploadServlet 中再添加代码段
if (filename != null) {
//通过工具类哪一个唯一的文件随机名称
String newFileName = UploadUtils.newFlieName(filename);
//通过工具类获得打散的二级三级目录
String newFliePath = UploadUtils.newFilePath(realPath, filename);
//文件----->上传(路径+文件名)
part.write(newFliePath + File.separator + newFileName);
part.delete();//清除临时缓存区
页面显示 服务器端产生二级三级目录