文件上传
一.文件上传原理
1.表单数据的编码方式:
<1>.text/plain:该编码方式指定了表单以文本方式发送请求。它主要适合直接使用表单发送电子邮件的方式(设置表单的action属性,如action="mailto:abc@126.com?subject=xyz").
<2>.application/x-www-form-urlencoded:这是默认的编码方式,该编码方式只处理表单域的value属性值,并将表单域的值按照 url编码的方式处理。
<3>.multipart/form-data:该编码方式以二进制的方式来处理表单中的数据,这种编码方式会把文件域所指定的文件内容也封装在请求中。
二.使用Commons-FileUpload上传文件
Commons-FileUpload组件是apache的Commons组件包中的一个组件:
下载地址:http://commons.apache.org/fileupload/
Commons-FileUpload组件还依赖一个Commons-IO组件:
下载地址:http://commons.apache.org/io/
1.上传一个文件:
步骤一:把以下两个jar包拷贝到工程的lib目录下面:
commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
步骤二:
编写一个upload.jsp文件,将<input type = "file".../>里面的enctype属性值设为“multipart/form-data”,jsp页面内容为:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>上传单个文件</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form action = "servlet/UploadServlet" method = "post" enctype = "multipart/form-data">
<table style = "text-align:right;">
<tr>
<td>上传文件:</td><td><input type = "file" name = "file"/></td>
</tr>
<tr>
<td>新文件名:</td>
<td><input type = "text" name = "filename" style = "width:200px"/></td>
</tr>
<tr>
<td></td>
<td><input type = "submit" value = "上传"/></td>
</tr>
</table>
</form>
</body>
</html>
try {
request.setCharacterEncoding("utf-8");// 设置处理请求参数的编码格式
response.setContentType("text/html;charset=utf-8");// 设置Content-Type字段值
PrintWriter out = response.getWriter();
FileItemFactory factory = new DiskFileItemFactory();// 使用Commons-UploadFile组件处理上传的文件数据
ServletFileUpload upload = new ServletFileUpload(factory); // 建立FileItemFactory对象
List<FileItem> items = upload.parseRequest(request); // 分析请求,并得到上传文件的FileItem对象
String uploadPath = this.getInitParameter("path");// 从web.xml文件中的参数中得到上传文件的路径
String filename = "";// 上传文件保存到服务器的文件名
InputStream is = null;// 当前上传文件的InputStream对象
for (FileItem item : items) { // 循环处理上传文件
if (item.isFormField()) {// 处理普通的表单域
if (item.getFieldName().equals("filename")) {
if (!item.getString().equals(""))// 如果新文件不为空,将其保存在filename中
filename = item.getString("utf-8");
}
} else if (item.getName() != null && !item.getName().equals("")) {// 处理上传文件
filename = item.getName().substring(
item.getName().lastIndexOf("\\") + 1);// 从客户端发送过来的文件上传路径中截取文件名
is = item.getInputStream();// 得到上传文件的InputStream对象
}
}
filename = uploadPath + filename;// 将路径和上传文件名组合成完整的服务端路径
if (new File(filename).exists()) {// 如果服务器已经存在和上传文件同名的文件,则输出提示消息
out.println("该文件已经存在,请为文件指定一个新的文件名!");
} else if (!filename.equals("")) {// 开始上传文件
FileOutputStream fos = new FileOutputStream(filename);// 用FileOutputStream打开服务端的上传文件
byte[] buffer = new byte[8192];int count = 0;
while ((count = is.read(buffer)) > 0) { // 开始读取上传文件的字节,并将其输出到服务端的上传文件输出流中
fos.write(buffer, 0, count);
}
fos.close();is.close();out.println("上传成功!!!");
}
} catch (Exception e) {
e.printStackTrace();
}
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>com.neusoft.upload.UploadServlet</servlet-class>
<init-param>
<param-name>path</param-name>
<param-value>d:\upload\</param-value>
</init-param>
</servlet>
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'uploadmore.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<script language = javascript">
function addFile(){
var uploadHTML = document.createElement("<input type = 'file' name = 'upload'/>");
document.getElementById("files").appendChild(uploadHTML);
uploadHTML = document.createElement("<p>");
document.getElementById("files").appendChild(uploadHTML);
}
</script>
</head>
<body>
<input type = "button" onclick = "addFile()" value = "添加文件"/>
<form action = "servlet/UploadMoreServlet" method= "post" enctype = "multipart/form-data">
<span id = "files">
<input type = "file" name = "upload"/><br/>
</span>
<input type = "submit" value = "上传"/>
</form>
</body>
</html>
try {
request.setCharacterEncoding("utf-8");// 设置处理请求参数的编码格式
response.setContentType("text/html;charset=utf-8");// 设置Content-Type字段值
PrintWriter out = response.getWriter();
FileItemFactory factory = new DiskFileItemFactory();// 使用Commons-UploadFile组件处理上传的文件数据
ServletFileUpload upload = new ServletFileUpload(factory); // 建立FileItemFactory对象
List<FileItem> items = upload.parseRequest(request); // 分析请求,并得到上传文件的FileItem对象
String uploadPath = this.getInitParameter("path");// 从web.xml文件中的参数中得到上传文件的路径
String filename = "";// 上传文件保存到服务器的文件名
for (FileItem item : items) { // 循环处理上传文件
if (!item.isFormField()) {
filename = item.getName();// 获得当前文件域中的上传文件名
if (filename.equals(""))// 当前文件域未输入文件名,则忽略此文件
continue;
// 生成当前上传文件在服务端的文件名(以当前毫秒作为文件名)
filename = uploadPath + System.currentTimeMillis()
+ filename.substring(filename.lastIndexOf("."));
FileOutputStream fos = new FileOutputStream(filename);
// 如果该文件已经在内存中,直接通过文件的字节数组来保存
if (item.isInMemory()) {
// 一次性将文件的内容写到服务端的相应文件中
fos.write(item.get());
} else {
InputStream is = item.getInputStream();
byte[] buffer = new byte[8192];
int count = 0;
while ((count = is.read(buffer)) > 0) { // 开始读取上传文件的字节,并将其输出到服务端的上传文件输出流中
fos.write(buffer, 0, count);
}
is.close();
}
fos.close();
}
}
out.println("上传成功!!!");
步骤四:在web.xml文件中配置服务端保存文件的路径,后要加上反斜杠:
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>UploadMoreServlet</servlet-name>
<servlet-class>com.neusoft.upload.UploadMoreServlet</servlet-class>
<init-param>
<param-name>path</param-name>
<param-value>d:\upload\</param-value>
</init-param>
</servlet>