介绍
上传文件是最常用的功能之一,如网购评论时要发图片,报考网站要上传个人信息等
实现html
创建 upload.jsp,关键内容如下:
<form method="post" enctype="multipart/form-data" action="upload">
上传图片:<input type="file" name="img"><br>
描述:<input type="text" name="descrip"><br>
<input type="submit">
</form>
关键:
method="post"必须是post方法enctype="multipart/form-data":enctype 是表单请求正文的类型,上传文件必须设置,表示以 流 的方式将数据发送给服务器<input type="file" name="img">:上传文件控件,注意名字
依赖jar包
像之前 request.getParameter() 的方式接收数据,是接收不到的
因为: 浏览器是以 流 的方式向服务发送数据,服务器也需要以 流 的方式 接收数据
以 流 的方式接收数据,比较复杂,好在 Apache 已经开发好了 jar包,我们直接使用即可:
常用类说明
FileItemFactory 和 DiskFileItemFactory
用于实例化 ServletFileUpload 类对象
FileItemFactory fif=new DiskFileItemFactory();
ServletFileUpload sfu=new ServletFileUpload(fif);
ServletFileUpload 类
用于处理上传数据
常用方法:
boolean isMultipartContext(HttpServletRequest request):判断是否文件上传Map<String,List<FileItem> parseRequest(HttpServletRequest request):解析上传数据,返回 MapMap中的key:是表单控件的 name 属性值
Map中的value:是
List<FileItem>类型,表单控件的 value 值。一般控件,那么该 List 只有一个元素,如果checkbox控件,则是多个元素
FileItem类
一个 FileItem对象 代表表单中一个控件,可以表示普通控件,也可以表示上传文件控件
常用方法:
String getFieldName():返回表单控件的 name 属性值String getString():返回表单控件的 value 值。如果是上传文件对象,是乱码,无意义。String getName():如果是上传文件对象,那么返回上传文件的名字,否则为nullvoid write(File file):将文件写入到指定位置boolean isFormField():true表示普通表单控件,false表示文件控件
实现Servlet
有缺点:不能上传同名文件
package servlet;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
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 org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@WebServlet(urlPatterns="/upload")
public class UploadServlet extends HttpServlet{
// 上传文件存储目录
public static final String UPLOAD_PATH = "upload";
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//判断是否文件上传
boolean isMC=ServletFileUpload.isMultipartContent(req);
if(isMC){
FileItemFactory fif=new DiskFileItemFactory();
ServletFileUpload sfu=new ServletFileUpload(fif);
// 构造保存上传文件的路径
String uploadPath = getServletContext().getRealPath("/"+UPLOAD_PATH) ;
//在开发时,是开发工具集成tomcat,所以不在本工程目录下
System.out.println("上传文件路径:"+uploadPath);
//通过File类对象,判断该目录是否存在,如果不存在,就创建该目录
File uploadPathFile=new File(uploadPath);
if(!uploadPathFile.exists()){ //判断是否存在
uploadPathFile.mkdirs(); // 创建目录
}
try {
//传入request,解析出上传文件
Map<String, List<FileItem>> map=sfu.parseParameterMap(req);
List<FileItem> imgs=map.get("img"); //获取上传的文件
List<FileItem> descrips=map.get("descrip"); //获取控件的值
// req.getParameter("descrip")//上传文件,不能通过这种方式获取
if(imgs!=null && !imgs.isEmpty()){
FileItem img=imgs.get(0); // 获取第一个文件(暂且不考虑上传多个文件)
File uploadFile=new File(uploadPathFile, img.getName());//拼装要保存文件的目录
img.write(uploadFile);// 将上传的文件,写入到该目录
}
//获取表单控件的值
if(descrips!=null && !descrips.isEmpty()){
String descrip=descrips.get(0).getString("utf-8");
System.out.println(descrip);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//根据情况,跳转到成功页面,或者输出一段文字
}
}
实现 Servlet
可以上传同名文件,会生成 新的文件名,文件名由 UUID生成,后缀是 原文件名的后缀
@WebServlet(urlPatterns="/upload")
public class UploadServlet extends HttpServlet{
// 上传文件存储目录
public static final String UPLOAD_PATH = "upload";
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//判断是否文件上传
boolean isMC=ServletFileUpload.isMultipartContent(req);
if(isMC){
FileItemFactory fif=new DiskFileItemFactory();
ServletFileUpload sfu=new ServletFileUpload(fif);
// 构造保存上传文件的路径
String uploadPath = getServletContext().getRealPath("/"+UPLOAD_PATH) ;
//在开发时,是开发工具集成tomcat,所以不在本工程目录下
System.out.println("上传文件路径:"+uploadPath);
//通过File类对象,判断该目录是否存在,如果不存在,就创建该目录
File uploadPathFile=new File(uploadPath);
if(!uploadPathFile.exists()){ //判断是否存在
uploadPathFile.mkdirs(); // 创建目录
}
try {
//传入request,解析出上传文件
Map<String, List<FileItem>> map=sfu.parseParameterMap(req);
List<FileItem> imgs=map.get("img"); //获取上传的文件
List<FileItem> descrips=map.get("descrip"); //获取控件的值
// req.getParameter("descrip")//上传文件,不能通过这种方式获取
if(imgs!=null && !imgs.isEmpty()){
FileItem img=imgs.get(0); // 获取第一个文件(暂且不考虑上传多个文件)
//重命名文件名字,防止文件名同名
String fileName=img.getName();
String newFileName = getNewFileName(fileName);
File uploadFile=new File(uploadPathFile,newFileName );//拼装要保存文件的目录
img.write(uploadFile);// 将上传的文件,写入到该目录
}
//获取表单控件的值
if(descrips!=null && !descrips.isEmpty()){
String descrip=descrips.get(0).getString("utf-8");
System.out.println(descrip);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//根据情况,跳转到成功页面,或者输出一段文字
}
/**
* 实现新的文件名,文件名由 UUID生成,后缀是 原文件名的后缀
* @param oldFileName
* @return
*/
private String getNewFileName(String oldFileName){
//获取原文件的后缀
int pos=oldFileName.lastIndexOf(".");//从右往左找到第一个 .
String suffix=oldFileName.substring(pos);
//用uuid作为文件名,后面还要拼装后缀
String newFileName=UUID.randomUUID().toString().replace("-", "")+suffix;
return newFileName;
}
}