文件上传的原理(看了视频后的个人理解):
文件上传,本质是就是将用户提交的文件,用io流写入服务器磁盘,遇到的问题就是如何将文件内容封装到请求中,如何再服务器端获取文件内容
由于post传输数据时,不需要再url中显示出来,而get要再url中显示出来。所以post传输的数据量大,可以达到2m,而get方法由于受到url长度限制,只能传递大概1024字节,所以文件上传需要使用post提交方式
如果使用默认enctype,表单提交,请求体中只包含文件名称,不包含文件内容,所以需要指定enctype="multipart/form-data"
上传到服务器,服务器要从request中解析出文件,文件再请求体中的存在方式:请求体会将内容分部分,分为普通文本项,上传文件1,上传文件2....
上传步骤编写:
1.在客户端(页面):
- 有一个input,type="file" name="file"。 form表单需要有属性enctype="multipart/form-data"。 提交方式是post,
2.在服务器端(action):
- 创建一个磁盘文件项工厂 DiskFileItemFactory
- 创建核心解析request类 ServletFileUpload
- 开始解析request对象,返回一个list集合
- list集合中保存表单的内容(分部分----普通文本项 或 上传文件项)
- 遍历list,获取内容
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
文件描述:<input type="text" name="filedesc" /><br>
上传文件:<input type="file" name="myfile" /><br>
<input type="submit" value="上传" />
</form>
//创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(1024*1024*3); //设置缓冲区大小为3m
//获取temp的绝对磁盘路径
String temp = getServletContext().getRealPath("/temp");
//设置临时文件存放位置
factory.setRepository(new File(temp));
//创建核心解析对象
ServletFileUpload upload = new ServletFileUpload(factory);
try {
//解析request
List<FileItem> list = upload.parseRequest(request);
//遍历list
for(FileItem fileItem:list){
//fileItem可能是普通文本项,也可能是文件上传项
if(fileItem.isFormField()){
//返回true,是普通文本项
//获取input的name
String name = fileItem.getFieldName();
//获取用户输入的值
String value = fileItem.getString();
System.out.println(name+":"+value);
}else{
//是上传文件项
//先获取文件的名称
String filename = fileItem.getName();
//获取文件的输入流
InputStream in = fileItem.getInputStream();
//向某个文件中写入
//向WebRoot/upload目录写入
String path = getServletContext().getRealPath("/upload");
//获取输出流
OutputStream os = new FileOutputStream(path+"/"+filename);
//io拷贝
int len = 0;
byte [] b = new byte[1024];
while((len = in.read(b))!= -1){
os.write(b, 0, len);
}
in.close();
os.close();
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DiskFileItemFactory
//两个构造方法
//DiskFileItemFactory() 和 DiskFileItemFactory(int sizeThreshold,javaio.File repository)
//sizeThreshold 设置缓冲区的大小,默认为10k
//repository 如果缓冲区大小小于上传文件的大小,产生临时文件,临时文件保存再repository目录下如果使用无参构造,可以用以下方法设置
//创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();factory.setSizeThreshold(1024*1024*3); //设置缓冲区大小为3m
//获取temp的绝对磁盘路径
String temp = getServletContext().getRealPath("/temp");
//设置临时文件存放位置
factory.setRepository(new File(temp));
ServletFileUpload
1.判断表单是否是enctype="multipart/form-data",如果是返回true 不是返回false
static boolean isMultipartContent(javax.servlet.http.HttpServletRequest request)
2.解析request,返回List集合,泛型是FileItem (文件项)
java.util.List parseRequest(javax.servlet.http.HttpServletRequest request)
3.设置上传的单个文件的大小
void setFileSizeMax(long fileSizeMax)
4.设置上传文件的总大小
void setSizeMax(long sizeMax)
5.设置上传文件的名称的编码
void setHeaderEncoding(java.lang.String encoding)
6.上传的时候都有进度条,此方法是用作监听
setProgressListener(ProgressListener pListener)
FileItem
代表文件项:封装的就是form表单的一部分
方法:
1.判断当前的fileItem对象是普通表单项还是上传文件项
boolean isFormField()
2.获取表单中的name的名称(标签的name)
java.lang.String getFieldName()
3.获取表单中普通项的值
java.lang.String getString()
4.获取表单中普通项的值(可以指定编码)
java.lang.String getString(String encoding)
5.获取文件的名称
java.lang.String getName()
6.获取文件的输入流
java.io.InputStream getInputStream()