第五章 文件上传

文件上传是WEB应用经常需要面对的问题,在大部分的时候,用户的请求参数是在表单域输入的字符串,但如果为表单元素设置enctype=”multipart/form-data”属性,则提交表单时不再以字符串方式提交请求参数,而是以二进制的方式提交请求,此时直接通过HttpServletRequest的getParameter方法无法正常获取请求参数的值,我们可以通过二进制流来获取请求内容—通过这种方式,就可以取得希望上传文件的内容,从而实现文件的上传.

上面介绍的文件上传方式是全手工的文件上传机制,这种方式编程麻烦,而且需要全手动地控制二进制流,相当烦琐.Java领域有两个常用的文件上传项目:Common-FileUpload和COS.

表单元素的enctype属性
大部分时候,无需要设置表单元素的enctype属性,我们只设置表单的action属性和method属性,其中action属性指定了表单提交到的URL,而method属性指定是以Post方式还是Get方式提交请求.

表单的enctype属性指定的是表单数据的编码方式,该属性有如下3个值:
1. application/x-www.form-urlencoded:这是默认的编码方式,它只处理表单域里的value属性值,采用这种编码方式,表单会将表单域的值处理成URL编码方式.
2. multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容,并封装到请求参数里.
3. text/plain:这种编码方式当表单的action属性为mailto:URL的形式时比较方便,这种方式主要适用于直接通过表单发送邮件的方式.

上传文本文件
新建一文本文件,保存时存为UTF-8格式
内容任意,可带中文文字
JSP
<%@page contentType="text/html; charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:set var="basePath" value="${pageContext.request.contextPath}" />
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>文件上传</title>
</head>
<body>
<form method="post" action="${basePath}/FileUploadServlet"
enctype="multipart/form-data">
测试字段1:
<input type="text" id="temp1" name="temp1" />
<br />
测试字段2:
<input type="text" id="temp2" name="temp2" />
<br />
选择文件:
<input type="file" id="file" name="file" />
<br />
测试字段3:
<input type="text" id="temp3" name="temp3" />
<br />
<input type="submit" value="上传" />
</form>
</body>
</html>
Servlet:
public class FileUploadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
BufferedReader br = request.getReader();
String temp = null;
while((temp =br.readLine()) != null){
System.out.println(temp);
}
}
}
可以看到输出为:
-----------------------------7d94e2a0734
Content-Disposition: form-data; name="temp1"

测试字段1
-----------------------------7d94e2a0734
Content-Disposition: form-data; name="temp2"

测试字段2
-----------------------------7d94e2a0734
Content-Disposition: form-data; name="file"; filename="C:\Documents and Settings\Administrator\My Documents\新建文本文档.txt"
Content-Type: text/plain

百 度 新 浪 腾 讯 搜 狐 网 易 谷 歌
凤 凰 网 央 视 网 新 华 网 人 民 网 中国移动 中国政府网
人 人 网 开 心 网 湖南卫视 汽车之家 赶 集 网 太平洋电脑网
东方财富 中华英才网 中 彩 网 赛 尔 号 智联招聘 携程旅行网
百度有啊 百 姓 网 360安全卫士 淘 宝 网 51个人空间 NBA中文网
工商银行 天龙八部 中关村在线 安居客房产网 太平洋汽车网 去哪儿网
京东网上商城 乐淘族鞋城 前程无忧人才网 卓越网上购物 当当网上购物 世纪佳缘交友
-----------------------------7d94e2a0734
Content-Disposition: form-data; name="temp3"

测试字段3
-----------------------------7d94e2a0734--
这个时候我们可以看到表单字段以及文件域的内容以流的方式已经传到后台来了,我们只需要将流中的内容解析出来,然后写入到文件中就可以达到文件上传的目的了.

上传二进制文件
public class FileUploadServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
BufferedReader br = request.getReader();
String temp = null;
while ((temp = br.readLine()) != null) {
if (temp.indexOf("filename") > 1) {
// 取扩展名
String fileExtension = temp.substring(temp.indexOf('.'), temp
.length() - 1);
br.readLine();
br.readLine();
File file = new File(request.getSession().getServletContext()
.getRealPath("/")
+ System.currentTimeMillis() + fileExtension);
//输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
String content = null;
while((content=br.readLine())!=null){
if(content.startsWith("-----------------------------")){
break;
}
byte[] b = content.getBytes();
for(int i=0; i<b.length; i++){
bos.write(b[i]);
}
//bos.write('\n');
}
bos.flush();
bos.close();
}
}
}
}
我的意思是用字符流读取JSP传过来的流,然后在流中,当读取到文件内容的时候,我就把字符串转换为byte[],然后再用字节流写入文件中,按道理应该是可以还原图片的,可是结果不行,

用第三方插件上传文件
commons-fileupload包
它的依赖包:
commons-io
示例:
public class FileUploadServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 创建上传工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(1796009048);
try {
// 处理HTTP请求,items是所有的表单项
List<FileItem> items = upload.parseRequest(request);
for (FileItem fileItem : items) {
// isFormField为true为普通表单项,否则为文件域
if (fileItem.isFormField()) {
// 表单字段名
String name = fileItem.getFieldName();
// 表单字段值
String value = fileItem.getString();
System.out.println("name=" + name + " value=" + value);
} else {
// 为文件域的情况
String fieldName = fileItem.getFieldName();
// 取文件名
String fileName = fileItem.getName();
// 取得文件类型
String contentType = fileItem.getContentType();
// 上传准备工作,取文件扩展名
// 取扩展名
String fileExtension = fileName.substring(fileName
.indexOf('.'), fileName.length());
// 以时间戳命名文件名
File file = new File(request.getSession()
.getServletContext().getRealPath("/")
+ System.currentTimeMillis() + fileExtension);
// 构造字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(file));
//如果文件内容完全在内存中
if(fileItem.isInMemory()){
bos.write(fileItem.get());
}else{
//如果文件内容不完全在内存中
BufferedInputStream bis = new BufferedInputStream(fileItem.getInputStream());
int i = 0;
while ((i = bis.read()) != -1) {
bos.write(i);
}
bis.close();
}
bos.flush();
bos.close();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值