文件的上传在我们的日常学习中是经常要使用的;浏览器在进行文件的上传都是经过流的形式进行传输的,在JavaWeb中进行文件的上传首先要完成以下几步:
1.下载好在JavaWeb项目中所要使用的jar包,
因为通常我们都是采用apache的开源工具common-fileupload这个文件上传组件;而common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
我们下载最新的jar包
- https://mvnrepository.com/artifact/commons-io/commons-io
- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
文件上传所要注意的事项
- 为保证服务器的安全,上传的文件一般都是保存到用户无法直接访问的目录下;如web-info下;
- 文件上传需要产生一个唯一的文件名,避免发生文件覆盖的现象;
- 可以设置文件的最大值,文件类型,判断文件的后缀名是否合法;
实例:
编译之前,一般会分为前端和后端,upload.jsp和index.jsp都是进行编译前端的页面的,做提示信息;
upload.jsp
- 在HTML页面input 必须有 name
<input type="file" name="filename">
- 表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-data
- 文件上传使用一定要使用post进行上传;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/file.do" method="post"
enctype="multipart/form-data">
<p>上传用户:<input type="text" name="username"></p>
<p>上传文件1:<input type="file"name="upload1"></p>
<p>上传文件2:<input type="file"name="upload2"></p>
<p><input type="submit"value="提交"></p>
</form>
</body>
</html>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/upload.jsp">进入上传页面</a>
</body>
</html>
FileServlet类
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象,(使用其parseRequest(HttpServletRequest) 方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。) 在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以,需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。
package com.zhang.demo;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.UUID;
public class FilesServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//判断上传的文件是普通表单还是带文件的表单,普通为true,else false;
if (!ServletFileUpload.isMultipartContent(request)) {
//如果是普通文件,直接返回
return;
}//如果通过了if,说明表单时带文件上传的
//创建上传文件的保存路径,建议在web-info下,用户无法访问直接上传的文件
String uploadpath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadfile = new File(uploadpath);
if (!uploadfile.exists()) {
//如果目录不存在,创建一个目录
uploadfile.mkdir();
}
//临时路径,临时文件超出了预期的大小,就会被传送到临时文件中,过后会转存到永久或者消除
String tempath = this.getServletContext().getRealPath("/WEN-INF/tmp");
File file = new File(tempath);
if (!file.exists()) {
//文件不存在,创建目录
file.mkdir();
}
//处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
//但是我们都建议使用 Apache的文件上传组件来实现,common-fileupload,它需要依赖于 commons-io组件;
//1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的;
DiskFileItemFactory factory = getDiskFileItemFactory(file);
//2.获取ServletFileUpload
ServletFileUpload upload = getServletFileUpload(factory);
//3.处理上传的文件
String msg = uploadParseRequest(upload, request, uploadpath);
//servlet请求转发信息
request.setAttribute("msg", msg);
request.getRequestDispatcher("info.jsp").forward(request, response);
} catch (FileUploadException e) {
e.printStackTrace();
}
}
public static DiskFileItemFactory getDiskFileItemFactory(File file) {
DiskFileItemFactory factory = new DiskFileItemFactory();
//通过工厂设置缓存区,如果文件大于缓存区,就会放入临时文件中
factory.setSizeThreshold(1024 * 1024);//缓存区大小1m
factory.setRepository(file);//临时文件的保存目录
return factory;
}
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传的进度
upload.setProgressListener(new ProgressListener() {
@Override
//pBytesRead:已经读取到的文件大小
//pContentLength:文件大小
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("总大小" + pContentLength + "已上传:" + pBytesRead);
}
});
//出现乱码
upload.setHeaderEncoding("UTF-8");
//设置单个文件的最大值
upload.setFileSizeMax(1024 * 1024 * 10);
//设置总共能够上传文件的大小
upload.setSizeMax(1024 * 1024 * 10);
return upload;
}
public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath)
throws FileUploadException, IOException {
String msg ="";
//3.将前端请求封装成为一个fileItem对象
List<FileItem> fileItems = upload.parseRequest(request);
System.out.println(fileItems.toString());
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()) {
//判断上传的文件是什么类型(普通表单还是带文件的表单)
String name = fileItem.getFieldName();
//处理乱码
String value = fileItem.getString("UTF-8");
System.out.println(name + ";" + value);
} else {//判断他是上传的文件
// ===============处理文件==================
//拿到文件名字
String uploadfileName = fileItem.getName();
System.out.println("上传的文件的名字:" + uploadfileName);
if (uploadfileName.trim().equals("") || uploadfileName==null) {
continue;
}
//获得上传文件名
String Filename = uploadfileName.substring(uploadfileName.lastIndexOf("\\") + 1);
//获得上传文件的后缀名
String FileExtName = uploadfileName.substring(uploadfileName.lastIndexOf(".") + 1);
/*
如果文件后缀名 fileExtName 不是我们所需要的
就直接return,不处理,告诉用户文件类型不对。
*/
System.out.println("文件信息 [件名:" + Filename + "---文件类型" + FileExtName + "]");
//可以使用UUID(唯一识别的通用码),保证文件名唯一;
//UUID.randomUUID(),随机生一个唯一识别的通用码;
String uuidpath = UUID.randomUUID().toString();
//================处理文件完毕================
//存到哪?uploadpath
String realpath = uploadPath + "\\" +uuidpath ;
//给每个文件创建一个对应的文件夹
File realPathFile = new File(realpath);
if (!realPathFile.exists()) {
realPathFile.mkdir();
}
//===============存放地址完毕=================
//获得文件上传的流
InputStream inputStream = fileItem.getInputStream();
//创建一个文件输出流
//差了一个文件,加上输出文件的名字+"/"+uuidFileName
FileOutputStream FOS = new FileOutputStream(realpath + "\\" + Filename);
//创建一个缓存区
byte[] buffer = new byte[1024 *1024];
//判断是否读取完毕
int len = 0;
//如果大于0,就是还有数据
while ((len = inputStream.read(buffer))>0) {
FOS.write(buffer, 0, len);
}
//关闭流
FOS.close();
inputStream.close();
msg = "文件上传成功";
fileItem.delete();//上传成功,删除临时文件
}
}
return msg;
}
}
需要注意的是:“ \\ ” 或 “ / ”是根据自己的电脑文件格式设置的;
info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>消息提示</title>
</head>
<body>
${msg}
</body>
</html>
web.xml
<servlet>
<servlet-name>FilesServlet</servlet-name>
<servlet-class>com.zhang.demo.FilesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FilesServlet</servlet-name>
<url-pattern>/file.do</url-pattern>
</servlet-mapping>
编译以上代码的运行的结果如下图所示:
1. 首先到了提示页面
2. 点击提示页面,进入上传页面,选择好文件就可以上传;
3. 在文件上传的同时可以从控制台看到文件的传送情况:
4.然后就可以在web-info下看到上传的文件