java文件上传
文件上传三个条件,
1,表单的提交方式是POST 2,enctype类型是multipart/form-data 3,提供文件上传域
常见的文件上传问题:
1,保证服务器的安全,意思是上传的文件的路径不能直接被用户访问到 ---------> 解决方案: 一般把上传的文件放在WEB-INF目录下
2,如果上传的文件足够多时,可能会出现重名的情况,而一旦重名就会被覆盖 --------->解决方案: 可以使用UUID让文件名唯一
3, 一个目录中的文件可能会很多 ----------->解决方案: 1,用日期打散目录 2,用文件名的hashcode打散目录,不过我觉得这个会带来新的问题,比如以后要找某个文件会难找
4,文件上传的大小,一般来说,web方式都不适合上传太大的文件 ------------>解决方案: 单个文件大小 ServletFileUpload.setFileSizeMax(字节),总的文件大小ServletFileUpload.setSizeMax(字节)
5,用户 没有上传文件 ------------->解决方案: 只要判断文件名是否为空即可
6,临时文件的问题,使用DiskFileItemFactory产生FileItem对象的时候,内部有一个缓存,默认情况下,当上传的文件大小大于10kb时,把文件用磁盘缓存下来,放在系统的临时目录下 -------------->解决方案: 如果是使用io,则在关闭流之后, 清理临时文件 FileItem.delete();
使用两个jar包 :commons-fileupload-1.2.2.jar commons-io-2.2.jar
下面是servlet的代码
UploadServlet.java
package com.it.web.servlet;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
public class UploadServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//判断 表单是否支持上传文件(也就是enctype类型是否为multipart/form-data
boolean isMulitpart=ServletFileUpload.isMultipartContent(request);
if(!isMulitpart){
throw new RuntimeException("你的表单不适合上传文件");
}
DiskFileItemFactory factory=new DiskFileItemFactory();//创建磁盘文件项工厂对象
ServletFileUpload sfu=new ServletFileUpload(factory); //通过工厂对象创建核心对象
sfu.setHeaderEncoding("UTF-8");//解决上传文件乱码
sfu.setFileSizeMax(1024*1024*3); //限制单个文件大小3m
//解析request,返回装有文件项的list集合
try {
List<FileItem> lists=sfu.parseRequest(request);
for(FileItem fileItem:lists){
//判断表单项是普通文本类型还是上传文件类型
if(fileItem.isFormField()){
OrdinaryFormField(fileItem); //普通
}else{
UploadFormField(fileItem,request,response); //上传文件类型
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
/**
* 文件上传类型
* @param fileItem
* @param request
* @param response
* @throws IOException
* @throws ServletException
*/
private void UploadFormField(FileItem fileItem, HttpServletRequest request,
HttpServletResponse response){
//1,得到文件名
String fileName=fileItem.getName();//问题1 : fileName可能包含路径
if(fileName==null || "".equals(fileName.trim())){
request.setAttribute("fileEmpty","您还未选文件");
try {
request.getRequestDispatcher("/upload1.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
return;
}
//解决问题1
if(fileName!=null){
fileName=FilenameUtils.getName(fileName);
}
//解决文件重名问题
fileName=UUID.randomUUID()+"_"+fileName;
//上传文件的存储路径
String realPath=this.getServletContext().getRealPath("/WEB-INF/upload");//该目录浏览器不能直接访问
File storyDirectory=new File(realPath);
if(!storyDirectory.exists()){
storyDirectory.mkdirs();
}
//解决同一个 目录下文件太多的问题,用天数大散目录
String childDirectory=makeChildDirectory(storyDirectory);
//将时间目录添加到路径下
File file=new File(storyDirectory,childDirectory+File.separator+fileName);
try {
fileItem.write(file);
response.sendRedirect(request.getContextPath()+"/success.jsp");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 按天数大散目录
* @param storyDirectory
* @return
*/
private String makeChildDirectory(File storyDirectory) {
Date date=new Date();
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
String dateDirectory=format.format(date);
File file=new File(storyDirectory,dateDirectory);
if(!file.exists()){
file.mkdirs();
}
return dateDirectory;
}
/**
* 普通文本类型
* @param fileItem
*/
private void OrdinaryFormField(FileItem fileItem) {
//得到字段名
String fieldName=fileItem.getFieldName();
//字段值
String fieldValue=null;
try {
fieldValue = fileItem.getString("UTF-8");//解决编码问题
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(fieldName+"\t"+fieldValue);
}
public void doPost(HttpServletRequest request,HttpServletResponse response){
this.doGet(request, response);
}
}
下面是jsp的代码和运行视图
upload1.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>上传文件</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/upload1Servlet" method="POST" enctype="multipart/form-data">
用户名:<input type="text" name="username"><br/>
上传:<input type="file" name="uploadfile"><br/>${fileEmpty}
<input type="submit" value="提交"/>
</form>
</body>
</html>
上传成功后会在WEB-INF目录 下多了一个upload目录,里面有上传的文件