用Apache工具做文件上传
1获得所接受文件要保存的路径
String path = getServletContext().getRealPath("/files");
2文件上传的临时目录,如不指定则为Tomcat/temps
File tempDir = new File("d:/a");
3创建用于解析文件的工厂类,同时设置缓冲区
注意这个类是Apache公司的jar包要导入两个jar包
DiskFileItemFactory fileFactory = new DiskFileItemFactory(1024*8, tempDir);
ServletFileUpload upload = new ServletFileUpload(fileFactory);
4设置每个上传文件最大值
upload.setFileSizeMax(1024*1024*5);
5设置所有上传文件大小的最大值
upload.setSizeMax(1024*1024*10);//10M
6开始解析–返回list集合
List<FileItem> list = upload.parseRequest(request);
7分流:分为一般表单文件和上传文件
if(item.isFormField()){//一般表单组件
String str = item.getString("utf-8");//以指定编码方式接受,以解决普通表单组件接受中文乱码
System.out.println("普通表单组件..."+str);
}else{//文件组件
}
8文件上传,文件拷贝
FileUtils.copyInputStreamToFile(item.getInputStream(), new File(path+"/"+fileName2));
小细节:
服务器中文件名不能用中文,而且文件名又要唯一所以我们用UUID来做
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String ext = fileName.substring(fileName.lastIndexOf("."));
String fileName2 = uuid+ext;
防黑处理1 在地址栏直接提交 ,则输出你请求的页面不支持get…
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//防黑处理1 在地址栏直接提交 ,则输出你请求的页面不支持get...
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("你请求的页面不支持此方式提交...");
}
对于response.setContentType("text/html;charset=utf-8");
而言如果是“multipart/form-data”表单,可以设置其中file组件的文件名,但对其中的普通表单组件无效。如果是我们以前用的“application/x-www-form-urlencoded”表单,可以设置其中的普通表单组件。
防黑2 非“multipart/form-data”表单提交
//法1: 手动解决
String type = request.getContentType();
if(!type.contains("multipart/form-data")){
response.getWriter().print("此中提交方式不支持...");
return;
}
//法2:使用上传工具解决
boolean boo = ServletFileUpload.isMultipartContent(request);
if(!boo){
response.getWriter().print("此中提交方式不支持...");
return;
}
对于一般表单组件,以指定编码方式接受,以解决普通表单组件接受中文乱码
String str = item.getString("utf-8");
目录打散
目录打散我们是借助于fileName.hashCode
取每后四位做一层目录。16*16的目录方式来做。
String dir1 = Integer.toHexString(fileName.hashCode() & 0xf);
String dir2 = Integer.toHexString((fileName.hashCode() & 0xf0)>>4);
File dir = new File(path+"/"+dir1+"/"+dir2);
if(!dir.exists()){
dir.mkdirs();
}
File file = new File(dir+"/"+fileName2);
文件上传进度条简易版
用监听器监听,过多久刷一次。
upload.setProgressListener(new ProgressListener() {
private int p=0;
//readedBytes:已上传字节数 countBytes:上传的总字节数 count:文件序号(从1开始的)
@Override
public void update(long readedBytes, long countBytes, int count) {
double d = readedBytes * 100.0 /countBytes;
int dd = (int) d;
if( dd != p ){
out.print("当前进度:"+dd+"<br/>");
p = dd;
}
}
});
纯前台进度条
用两个div来做,通过JavaScript来设置里面那个div的width。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script type="text/javascript">
function start(){
a=0;
time = window.setInterval(run, 1000);
}
var a=0;
function run(){
a+=10;
if(a>100){
window.clearInterval(time);
return;
}
var div = document.getElementById("divPro");
div.style.width = a+"%";
}
function stop(){
window.clearInterval(time);
}
function resume(){
window.clearInterval(time);
time = window.setInterval(run, 1000);
}
</script>
</head>
<body>
<h2>进度条演示</h2>
<div style="border: 2px solid green; width: 300px;height: 30px; ">
<div id="divPro" style="background:red; width:30%; height:100%"></div>
</div>
<button onclick="start()">启动</button>
<button onclick="stop()">停止</button>
<button onclick="resume()">恢复</button>
</body>
</html>
本文完整代码如下:
index.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>
<title>演示request和response用法</title>
</head>
<body>
<!--通过request.getContextPath()可以把项目根目录(项目名)写活 -->
<form action="<%=request.getContextPath() %>/requestDemo" method="post">
姓名:<input type="text" name="name" /><br/>
<input type="submit" value="提交"/>
</form>
<!-- 演示表单参数的接受 -->
<form action="<%=request.getContextPath() %>/param" method="post">
姓名:<input type="text" name="name" /><br/>
年龄:<input type="text" name="age" /><br/>
<input type="checkbox" name="hoby" value="music" />音乐
<input type="checkbox" name="hoby" value="tv" />电视
<input type="checkbox" name="hoby" value="game" />游戏<br/>
<input type="radio" name="sex" value="0" checked="checked" >男
<input type="radio" name="sex" value="1">女
<input type="submit" value="提交"/>
</form>
<!-- 演示文件上传 -->
<h2>文件上传手动版</h2>
<form action="<%=request.getContextPath() %>/upload1" method="post" enctype="multipart/form-data">
文件名:<input type="file" name="fileName">
<input type="submit" value="上传">
</form>
<!-- 上面这种手动上传 的方法不好。要自己解析,麻烦,我们用阿帕奇公司-Commons-io.jar 和 Commos-fileupload.jar写好的去做文件上传 -->
<!-- 以下演示使用Apache公司的工具做上传 -->
<h1>以下演示使用Apache公司的工具做上传 单项文件上传</h1>
<form action="<%=request.getContextPath() %>/upload2" method="post" enctype="multipart/form-data">
文件名:<input type="file" name="fileName">
<input type="submit" value="上传">
</form>
<form action="<%=request.getContextPath() %>/upload2" method="post" enctype="multipart/form-data">
文件1:<input type="file" name="fileName">
文件1的说明:<input type="text" name="desc1">
文件2:<input type="file" name="fileName2">
文件2的说明:<input type="text" name="desc2">
<input type="submit" value="上传">
</form>
<br/>
<br/>
<h1>完整点的文件上传</h1>
<form action="<%=request.getContextPath() %>/upload3" method="post" enctype="multipart/form-data">
文件1:<input type="file" name="fileName">
文件1的说明:<input type="text" name="desc1">
文件2:<input type="file" name="fileName2">
文件2的说明:<input type="text" name="desc2">
<input type="submit" value="上传">
</form>
<br/><br/>
<a href = "progress.jsp">纯前台的进度条</a>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name></display-name>
<servlet>
<servlet-name>RequestDemo</servlet-name>
<servlet-class>cn.hncu.servlets.RequestDemo</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>Hello</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>ParamerServlet</servlet-name>
<servlet-class>cn.hncu.servlets.ParamerServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>UpFileServlet</servlet-name>
<servlet-class>cn.hncu.servlets.UpFileServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>cn.hncu.servlets.upload.UploadServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>UpLoadServlet3</servlet-name>
<servlet-class>cn.hncu.servlets.upload.UpLoadServlet3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestDemo</servlet-name>
<url-pattern>/requestDemo</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ParamerServlet</servlet-name>
<url-pattern>/param</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>UpFileServlet</servlet-name>
<url-pattern>/upload1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/upload2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>UpLoadServlet3</servlet-name>
<url-pattern>/upload3</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
UploadServlet
package cn.hncu.servlets.upload;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletException;
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.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
public class UploadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//防黑处理1 在地址栏直接提交 ,则输出你请求的页面不支持get...
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("你请求的页面不支持此方式提交...");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
//注意,下面这句设置中文,如果是“multipart/form-data”表单,可以设置其中file组件的文件名,但对其中的普通表单组件无效。
//注意,下面这句设置中文,如果是我们以前用的“application/x-www-form-urlencoded”表单,可以设置其中的普通表单组件。
response.setContentType("text/html;charset=utf-8");
//1上传文件的保存路径
String path = getServletContext().getRealPath("/files");
//防黑2 非“multipart/form-data”表单提交
//法1: 手动解决
// String type = request.getContentType();
// if(!type.contains("multipart/form-data")){
// response.getWriter().print("此中提交方式不支持...");
// return;
// }
//法2:使用上传工具解决
boolean boo = ServletFileUpload.isMultipartContent(request);
if(!boo){
response.getWriter().print("此中提交方式不支持...");
return;
}
//2文件上传的临时目录,如不指定则为tomcat/temps
File tempDir = new File("d:/a");
//3创建用于解析文件的工厂类,同时设置缓冲区大小和位置
DiskFileItemFactory fileFactory = new DiskFileItemFactory(1024*8, tempDir);
ServletFileUpload upload = new ServletFileUpload(fileFactory);
//4设置每个文件的最大值
upload.setFileSizeMax(1024*1024*5);
//5设置所有文件大小之和的最大值
upload.setSizeMax(1024*1024*10);//10M
//6开始解析request--->返回list集合
try {
List<FileItem> list = upload.parseRequest(request);
//7分流:分为文件组件和一般表单组件
for(FileItem item : list) {
if(item.isFormField()){//一般表单组件
String str = item.getString("utf-8");//以指定编码方式接受,以解决普通表单组件接受中文乱码
System.out.println("普通表单组件..."+str);
}else{//文件组件
//防黑3 用户不选择文件提交
if(item.getSize()==0){
continue;
}
//文件名
String fileName = item.getName();
//服务器中名字不能用中文,但是文件名又要唯一我们用UUID来做
System.out.println("上传文件为:"+fileName);
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String ext = fileName.substring(fileName.lastIndexOf("."));
String fileName2 = uuid+ext;
// System.out.println(path);
// System.out.println(fileName2);
//Apache公司自己帮我们做好了写文件的工具
//真正的文件内容在 item.getInputStream() 当中
FileUtils.copyInputStreamToFile(item.getInputStream(), new File(path+"/"+fileName2));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
UpLoadServlet3
package cn.hncu.servlets.upload;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletException;
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.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
public class UpLoadServlet3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//防黑处理1 在地址栏直接提交 ,则输出你请求的页面不支持get...
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("你请求的页面不支持此方式提交...");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
//注意,下面这句设置中文,如果是“multipart/form-data”表单,可以设置其中file组件的文件名,但对其中的普通表单组件无效。
//注意,下面这句设置中文,如果是我们以前用的“application/x-www-form-urlencoded”表单,可以设置其中的普通表单组件。
response.setContentType("text/html;charset=utf-8");
final PrintWriter out = response.getWriter();
//1上传文件的保存路径
String path = getServletContext().getRealPath("/files");
//防黑2 非“multipart/form-data”表单提交
//法1: 手动解决
// String type = request.getContentType();
// if(!type.contains("multipart/form-data")){
// response.getWriter().print("此中提交方式不支持...");
// return;
// }
//法2:使用上传工具解决
boolean boo = ServletFileUpload.isMultipartContent(request);
if(!boo){
response.getWriter().print("此中提交方式不支持...");
return;
}
//2文件上传的临时目录,如不指定则为tomcat/temps
File tempDir = new File("d:/a");
//3创建用于解析文件的工厂类,同时设置缓冲区大小和位置
DiskFileItemFactory fileFactory = new DiskFileItemFactory(1024*8, tempDir);
ServletFileUpload upload = new ServletFileUpload(fileFactory);
//4设置每个文件的最大值
upload.setFileSizeMax(1024*1024*5);
//5设置所有文件大小之和的最大值
upload.setSizeMax(1024*1024*10);//10M
//文件上传进度条基础版
upload.setProgressListener(new ProgressListener() {
private int p=0;
//readedBytes:已上传字节数 countBytes:上传的总字节数 count:文件序号(从1开始的)
@Override
public void update(long readedBytes, long countBytes, int count) {
double d = readedBytes * 100.0 /countBytes;
int dd = (int) d;
if( dd != p ){
out.print("当前进度:"+dd+"<br/>");
p = dd;
}
}
});
//6开始解析request--->返回list集合
try {
List<FileItem> list = upload.parseRequest(request);
//7分流:分为文件组件和一般表单组件
for(FileItem item : list) {
if(item.isFormField()){//一般表单组件
String str = item.getString("utf-8");//以指定编码方式接受,以解决普通表单组件接受中文乱码
System.out.println("普通表单组件..."+str);
}else{//文件组件
//防黑3 用户不选择文件提交
if(item.getSize()==0){
continue;
}
//文件名
String fileName = item.getName();
fileName = fileName.substring(fileName.lastIndexOf("/")+1);
//服务器中名字不能用中文,但是文件名又要唯一我们用UUID来做
System.out.println("上传文件为:"+fileName);
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String ext = fileName.substring(fileName.lastIndexOf("."));
String fileName2 = uuid+ext;
//打散目录
String dir1 = Integer.toHexString(fileName.hashCode() & 0xf);
String dir2 = Integer.toHexString((fileName.hashCode() & 0xf0)>>4);
File dir = new File(path+"/"+dir1+"/"+dir2);
if(!dir.exists()){
dir.mkdirs();
}
File file = new File(dir+"/"+fileName2);
// System.out.println(path);
// System.out.println(fileName2);
//Apache公司自己帮我们做好了写文件的工具
//真正的文件内容在 item.getInputStream() 当中
//FileUtils.copyInputStreamToFile(item.getInputStream(), new File(path+"/"+fileName2));
try {
item.write(file);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
progress.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script type="text/javascript">
function start(){
a=0;
time = window.setInterval(run, 1000);
}
var a=0;
function run(){
a+=10;
if(a>100){
window.clearInterval(time);
return;
}
var div = document.getElementById("divPro");
div.style.width = a+"%";
}
function stop(){
window.clearInterval(time);
}
function resume(){
window.clearInterval(time);
time = window.setInterval(run, 1000);
}
</script>
</head>
<body>
<h2>进度条演示</h2>
<div style="border: 2px solid green; width: 300px;height: 30px; ">
<div id="divPro" style="background:red; width:30%; height:100%"></div>
</div>
<button onclick="start()">启动</button>
<button onclick="stop()">停止</button>
<button onclick="resume()">恢复</button>
</body>
</html>