简介
对于文件上传,客户端需要一个上传文件的表单 服务端则需要在接收到表单后通过IO将其存储到磁盘里。
客户端
主要需要准备一个表单
分析请求
服务器端(基于Servlet)
-
通过request获取请求体的内容
-
解析请求体 多部件上传的特点是,每个input都是一个表单项.
根据分隔符将请求中所有的内容,切割成数组,数组中的每一个元素 都是一个表单项
-
遍历数组,分清楚那个是普通的表单项, 哪个是 文件上传项
如何区分? 判断是否有 filename
-
获取到普通表单项中的内容,通过属性name获取
-
获取文件上传项内容
文件名: filname = aaa.txt
文件内容:
-
使用IO将文件内容,保存到服务器中
FileUpload
是一个maven的dependency
FileUpload使用步骤:
1、创建磁盘文件项工厂
2、创建文件上传的核心类
3、解析request---获得文件项集合
4、遍历文件项集合
5、判断普通表单项/文件上传项
示例代码,展示了需要用到的API。注意在IO的时候使用了IOutils,这也是一个maven的dependency。当然不用也没问题,我们已经获得了输入流和输出流,所以接下来还是很好做的。
@WebServlet("/upload")
public class FileUploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//1.创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2.创建文件上传核心类
ServletFileUpload upload = new ServletFileUpload(factory);
//2.1 设置上传文件名的编码
upload.setHeaderEncoding("utf-8");
//2.2 判断表单是否是文件上传表单
boolean multipartContent = upload.isMultipartContent(req);
//2.3 是文件上传表单
if(multipartContent){
//3. 解析request ,获取文件项集合
List<FileItem> list = upload.parseRequest(req);
if(list != null){
//4.遍历获取表单项
for (FileItem item : list) {
//5. 判断是不是一个普通表单项
boolean formField = item.isFormField();
if(formField){
//普通表单项, 当 enctype="multipart/form-data"时, request的getParameter()方法 无法获取参数
String fieldName = item.getFieldName();
String value = item.getString("utf-8");//设置编码
System.out.println(fieldName + "=" + value);
}else{
//文件上传项
//文件名
String fileName = item.getName();
//避免图片名重复 拼接UUID
String newFileName = UUIDUtils.getUUID()+"_"+ fileName;
//获取输入流
InputStream in = item.getInputStream();
//创建输出流 输出到H盘
FileOutputStream fos = new FileOutputStream("H:/upload/" +newFileName);
//使用工具类IOUtils,copy文件
IOUtils.copy(in,fos);
//关闭流
fos.close();
in.close();
}
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
部署图片到tomcat(涉及到idea)
- 将项目部署到webapps
将部署方式改变为 war模式,把项目部署在tomcat的webapps下(在idea里只需要简单切换一下即可)
- idea中部署项目两种方式
- war模式:将项目以war包的形式上传真实到服务器的webapps目录中;
- war exploded模式:仅仅是目录的映射,就相当于tomcat在项目源文件夹中启动一样;
2.在webapps中创建upload目录
upload目录专门用来保存上传过来的图片
3.修改代码,将图片上传到服务器
- 修改图片的输出路径
- 获取到项目的运行目录信息
- 截取到webapps的 目录路径
- 拼接输出路径,将图片保存到upload
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//1.创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2.创建文件上传核心类
ServletFileUpload upload = new ServletFileUpload(factory);
//2.1 设置上传文件名的编码
upload.setHeaderEncoding("utf-8");
//2.2 判断表单是否是文件上传表单
boolean multipartContent = upload.isMultipartContent(req);
//2.3 是文件上传表单
if(multipartContent){
//3. 解析request ,获取文件项集合
List<FileItem> list = upload.parseRequest(req);
if(list != null){
//4.遍历获取表单项
for (FileItem item : list) {
//5. 判断是不是一个普通表单项
boolean formField = item.isFormField();
if(formField){
//普通表单项, 当 enctype="multipart/form-data"时, request的getParameter()方法 无法获取参数
String fieldName = item.getFieldName();
String value = item.getString("utf-8");//设置编码
System.out.println(fieldName + "=" + value);
}else{
//文件上传项
//文件名
String fileName = item.getName();
//避免图片名重复 拼接UUID
String newFileName = UUIDUtils.getUUID()+"_"+ fileName;
//获取上传文件的内容
InputStream in = item.getInputStream();
String path = this.getServletContext().getRealPath("/");
//获取到 webapps路径,
String webappsPath = path.substring(0, path.indexOf("projectName"));
OutputStream out = new FileOutputStream(webappsPath+"/upload/"+newFileName);
//拷贝文件到服务器
IOUtils.copy(in,out);
out.close();
in.close();
}
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
补充
代码里用到了一个UUIDUtils,其实就是自己写的一个类而已。
public class UUIDUtils {
//获取唯一ID的 方法
public static String getUUID() {
return UUID.randomUUID().toString().replace("-", "");
}
}