*1.文件上传_快速入门
一、文件上传
1.提供表单允许用户通过表单选择文件进行上传
2.在Servlet中将上传的文件保存在服务器的硬盘中
get请求参数最大1kb。
表单必须是POST提交
文件输入框必须有name属性,只有有name属性的输入项浏览器才会进行提交
需要设置enctype属性值为multipart/form-data
POST /Day15/upload.jsp HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://localhost/Day15/upload.jsp
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Content-Type: multipart/form-data; boundary=---------------------------7de1e62806e0
Accept-Encoding: gzip, deflate
Host: localhost
Content-Length: 394
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=818C14110CA7BFD1FC90610866A220E8
-----------------------------7de1e62806e0
Content-Disposition: form-data; name="description1"
xxxx
-----------------------------7de1e62806e0
Content-Disposition: form-data; name="description2"
zzzz
-----------------------------7de1e62806e0
Content-Disposition: form-data; name="file1"; filename="ip.txt"
Content-Type: text/plain
192
-----------------------------7de1e62806e0--
导包,Apache的两个。
ioutils:
package com.itheima.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class IOUtils {
private IOUtils() {
}
public static void In2Out(InputStream in,OutputStream out) throws IOException{
byte [] bs = new byte[1024];
int i = 0;
while((i=in.read(bs))!=-1){
out.write(bs,0,i);
}
}
public static void close(InputStream in,OutputStream out){
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}finally{
in = null;
}
}
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}finally{
out = null;
}
}
}
}
*2.文件上传_细节问题
DiskFileItemFactory
public DiskFileItemFactory(int sizeThreshold, java.io.File repository)
public DiskFileItemFactory()
public void setSizeThreshold(int sizeThreshold) --用来设定内存缓冲区的大小,默认是10k
public void setRepository(java.io.File repository) --设定临时文件夹的大小
临时文件也要删除。
如果选中文资源:
setheadencoding:
setProgressListener(ProgressListener pListener) 实时监听文件上传状态 [后面再讲]
FileItem
boolean isFormField() 判断FileItem是一个文件上传对象还是普通表单对象
如果是一个普通字段项可以调用:
String getFieldName() 获得普通表单对象的name属性
String getString(String encoding) 获得普通表单对象的value属性,可以用encoding进行编码设置
如果是一个文件上传项:
String getName() 获得上传文件的文件名(有些浏览器会携带客户端路径)
InputStream getInputStream() 获得上传文件的输入流
delete() 在关闭FileItem输入流后,删除临时文件
*3.JAVASCRIPT实现多表单上传
<%@ 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 addOne(){
var fdiv = document.getElementById("fdiv");
fdiv.innerHTML += '<div><input type="file" name="file1" /><input type="button" value="不要了.." onclick="delOne(this)"/><br><div>';
}
function delOne(obj){
obj.parentNode.parentNode.removeChild(obj.parentNode);
}
</script>
</head>
<body>
<h1>文件上传</h1><hr>
<input type="button" id="addBut" onclick="addOne()" value="加一个..."/>
<form action="${pageContext.request.contextPath }/servlet/UploadServlet" method="POST" enctype="multipart/form-data">
<div id="fdiv"></div>
<input type="submit" value="上传"/>
</form>
</body>
</html>
*4.文件上传_保存位置
分目录存放文件:
根据hash值存放。
文件存放应该注意的问题:
1.upload文件夹和temp文件夹都要放在web-inf目录下保护起来,防止上传入侵和访问其他用户上传资源的问题
2.文件名要拼接uuid保证唯一
3.文件要分目录存储保证同一目录下不要有过多的文件,分目录的算法有很多,介绍了一种根据hash值分目录算法
*5.文件上传监视
//--设置文件上传监听
fileUpload.setProgressListener(new ProgressListener(){
Long beginTime = System.currentTimeMillis();
public void update(long bytesRead, long contentLength, int items) {
BigDecimal br = new BigDecimal(bytesRead).divide(new BigDecimal(1024),2,BigDecimal.ROUND_HALF_UP);
BigDecimal cl = new BigDecimal(contentLength).divide(new BigDecimal(1024),2,BigDecimal.ROUND_HALF_UP);
System.out.print("当前读取的是第"+items+"个上传项,总大小"+cl+"KB,已经读取"+br+"KB");
//剩余字节数
BigDecimal ll = cl.subtract(br);
System.out.print("剩余"+ll+"KB");
//上传百分比
BigDecimal per = br.multiply(new BigDecimal(100)).divide(cl,2,BigDecimal.ROUND_HALF_UP);
System.out.print("已经完成"+per+"%");
//上传用时
Long nowTime = System.currentTimeMillis();
Long useTime = (nowTime - beginTime)/1000;
System.out.print("已经用时"+useTime+"秒");
//上传速度
BigDecimal speed = new BigDecimal(0);
if(useTime!=0){
speed = br.divide(new BigDecimal(useTime),2,BigDecimal.ROUND_HALF_UP);
}
System.out.print("上传速度为"+speed+"KB/S");
//大致剩余时间
BigDecimal ltime = new BigDecimal(0);
if(!speed.equals(new BigDecimal(0))){
ltime = ll.divide(speed,0,BigDecimal.ROUND_HALF_UP);
}
System.out.print("大致剩余时间为"+ltime+"秒");
System.out.println();
}
});