文件上传案例
1.浏览器端说明
- 请求方式为post
- 采用form表单提交,Input标签类型位file
- form表单的enctype属性值设置为multipart/form-data
jsp代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/u" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" name="提交">
</form>
</body>
</html>
2.配置xml文件
<servlet>
<servlet-name>uploadServlet</servlet-name>
<servlet-class>com.example.servlet.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>uploadServlet</servlet-name>
<url-pattern>/u</url-pattern>
</servlet-mapping>
3.servlet测试
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("up");
}
}
4.抓包工具抓包
这时如果通过servlet中req.getParameter的方式拿不到对应的名称
5.上传依赖的jar包
可以在http://tomcat.apache.org/官网下载 http://commons.apache.org/proper/commons-fileupload/
下载地址:
链接:https://pan.baidu.com/s/1o5IujerfmNKkO5-uI9yIuw
提取码:p2s4
6.实际操作
- 判定请求中是否有文件上传
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
- 基于磁盘创建工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
- 创建新的文件上载处理程序
ServletFileUpload upload = new ServletFileUpload(factory);
- 解析请求,返回一列表
List<FileItem> items = upload.parseRequest(request);
- 循环遍历FileItem判定是否是普通的表单项
next.isFormField()
5.1 如果是普通表单项,通过String fieldName = next.getFieldName();
拿到表单项的name属性,next.getString();
拿到表单控件的值
5.2 如果是文件表单next.getFieldName()
拿到控件的name属性,next.getName()
拿到上传文件的原始名,next.getInputStream()
拿到文件的二进制流内容 - 如果是文件,则使用二进制输入流进行文件输入
完整代码:
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if(ServletFileUpload.isMultipartContent(req)){
//创建基于磁盘的FileItemFactory
DiskFileItemFactory factory = new DiskFileItemFactory();
//基于FileItemFactory创建文件上传的操作对象
ServletFileUpload upload = new ServletFileUpload(factory);
//解析请求
try {
List<FileItem> items = upload.parseRequest(req);
Iterator<FileItem> iterator = items.iterator();
//循环遍历
while (iterator.hasNext()){
//拿到每个FileItem
FileItem next = iterator.next();
//判定FileItem是否是普通的表单项
if(next.isFormField()){
String fieldName = next.getFieldName();
String string = next.getString();
System.out.println(fieldName);
System.out.println(string);
}else {//是文件上传项
String fieldName = next.getFieldName();//拿到控件name属性
String name = next.getName();//拿到文件的原始名
InputStream inputStream = next.getInputStream();//二进制文件内容流
//创建文件保存路径
String realPath = getServletContext().getRealPath("/WEB-INF/source");
File file = new File(realPath);
file.mkdirs();
//利用二进制流进行写入
OutputStream outputStream = new FileOutputStream(new File(realPath,name));
byte[] buffer = new byte[1024];
int len = -1;
while ((len = inputStream.read(buffer,0,buffer.length))!=-1){
outputStream.write(buffer,0,len);
}
//关闭流
outputStream.close();
inputStream.close();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
}
但是当普通表单控件传入时会有中文乱码的问题:
在form表单中加入一个input-text标签,写入输出结果:
可以看到文件域的名字并没有乱码
解决乱码问题:string = new String(string.getBytes("iso-8859-1"),"utf-8");
7.commons-IO提供了对文件流的更简单的操作方式
FileUtils工具类
说明文档位置:http://commons.apache.org/proper/commons-io/apidocs/index.html
使用输入流复制到文件位置实现上传,
并且文件上传路径不存在可以默认创建,流使用完毕后自动关闭。
简化后的代码:
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if(ServletFileUpload.isMultipartContent(req)){
//创建基于磁盘的FileItemFactory
DiskFileItemFactory factory = new DiskFileItemFactory();
//基于FileItemFactory创建文件上传的操作对象
ServletFileUpload upload = new ServletFileUpload(factory);
//解析请求
try {
List<FileItem> items = upload.parseRequest(req);
Iterator<FileItem> iterator = items.iterator();
//循环遍历
while (iterator.hasNext()){
//拿到每个FileItem
FileItem next = iterator.next();
//判定FileItem是否是普通的表单项
if(next.isFormField()){
String fieldName = next.getFieldName();//拿到控件name属性
String string = next.getString();//拿到控件的值
string = new String(string.getBytes("iso-8859-1"),"utf-8");
}else {//是文件上传项
String fieldName = next.getFieldName();//拿到控件name属性
String name = next.getName();//拿到文件的原始名
System.out.println(name);
InputStream inputStream = next.getInputStream();//二进制文件内容流
String realPath = getServletContext().getRealPath("/WEB-INF/source");
FileUtils.copyInputStreamToFile(inputStream,new File(realPath,name));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
}