javaweb之文件上传总结

来源:互联网 发布:知否txt微盘 编辑:程序博客网 时间:2024/05/22 13:25

一。文件上传:
是指允许客户将本地文件,上传到服务器端 
常见的应用:上传照片、上传新闻图片、上传附件 
文件上传编程基本步骤:
 1、在用户页面中添加上传输入项 (客户端页面操作)也就是编写一个jsp页面里面编写一个表单提交
 <from action="跳转路径" method="post" enctype="multipart/from-data">
 <input type="file" name="fileUpload"/>
 <input type ="submit" value="上传"/>
 </from>
 注意事项:
 1) 必须为文件上传input 提供name属性,否则文件上传内容不会被表单提交 
 2) 表单的提交是post (get提交数据在url地址上显示,有长度限制) 
 3) 设置enctype=multipart 使得文件上传编码 ----- MIME编码格式
常用文件上传API : 
 1) JSP独立开发年代 jsp-smartupload ---- JSP Model1 
 jspSmartUpload是一个可免费使用的全功能的文件上传下载组件,适于嵌入执行上传下载操作的JSP文件中。
 2) JSP+Servlet 开发web应用 Apache commons-fileupload ---- JSP Model2
 FileUpload 是 Apache commons下面的一个子项目,用来实现Java环境下面的文件上传功能,与常见的SmartUpload齐名。
 3) Servlet3.0规范中提供对文件上传的支持 
Apache commons-fileupload 的使用:
 1) 去 http://commons.apache.org/fileupload/ 下载fileupload jar包
 同时下载 commons-fileupload 和  commons-io 两个包  -------- 因为fileupload依赖io包 
 2) 将jar包导入 web 工程WEB-INF/lib下 
 3) 编写步骤:
 步骤一:获得DiskFileItemFactory 文件项工厂
 步骤二:通过工厂获得文件上传请求核心解析类 ServletFileUpload构造函数中传入工厂示例对象 
 步骤三:使用ServletFileUpload对request进行解析  ---- 获得很多个FileItem
 步骤四:对每个FileItem进行操作 判断FileItem是不是个文件上传项FileItem.isFormField()
   返回boolean true代表不是一个文件上传项 false代表是一个文件上传项
 --------文件上传项是指获得的input标签type是不是一个上传文件的标签
 代表普通字段FileItem 
 getFieldName();  ---- 获得表单项name属性
 getString(); ----- 获得表单项value

 代表文件上传FileItem
 getInputStream() --- 获得文件内容输入流
 getName() ------ 获得上传文件名称(注意:IE6版本获得的是文件的全路径需要进行切割去到文件名)
  int index = 取到的文件全路径.lastIndexOf("\\");找到最后一个\出现的位置
  if (index != -1)
  {
   filename = 取到的文件全路径.substring(index + 1);// 获得真实文件名
  }
二、commons-fileupload 核心API分析:
1、DiskFileItemFactory 磁盘文件项工厂类 
public DiskFileItemFactory(int sizeThreshold, java.io.File repository)  构造工厂时,指定内存缓冲区大小和临时文件存放位置
public void setSizeThreshold(int sizeThreshold) 设置内存缓冲区大小,默认10K
public void setRepository(java.io.File repository)设置临时文件存放位置,默认System.getProperty("java.io.tmpdir").
什么是内存缓冲区: 上传文件时,上传文件的内容优先保存在内存缓冲区中,当上传文件大小超过缓冲区大小时,就会在服务器端产生临时文件 
什么是临时文件: 保存超过了内存缓冲区大小上传文件而产生临时文件 
产生的临时文件可以通过 FileItem的delete方法删除

2、ServletFileUpload 文件上传核心类 
static boolean  isMultipartContent(javax.servlet.http.HttpServletRequest request)  判断request的编码方式是否为multipart/form-data
java.util.List  parseRequest(javax.servlet.http.HttpServletRequest request) 解析request,将请求体每个部分封装FileItem对象,返回List<FileItem>
void setFileSizeMax(long fileSizeMax) 设置单个文件上传大小
void setSizeMax(long sizeMax) 设置总文件上传大小 
void setHeaderEncoding(java.lang.String encoding)  设置编码集 解决上传文件名乱码 ***** 
void setProgressListener(ProgressListener pListener) 
设置文件上传监听器(用来监控文件上传进度)上传时间、剩余大小、速度、剩余时间 
3、FileItem 表示文件上传表单中 每个数据部分 
boolean isFormField()  判断该数据项是否为文件上传项,true 不是文件上传 false 是文件上传
if(fileItem.isFormField()){
   // 不是上传项
   java.lang.String getFieldName()  获得普通表单项name属性
   java.lang.String getString() / java.lang.String getString(java.lang.String encoding) 获得普通表单项value属性 传入编码集用来解决输入value乱码
}else{
   // 是上传项
   java.lang.String getName() 获得上传文件名 (注意IE6存在路径)
   java.io.InputStream  getInputStream() 获得上传文件内容输入流
   // 上传文件
   void delete()  删除临时文件(删除时,必须要管理输入输出流)
}
注意事项:因为文件上传表单采用编码方式multipart/form-data 与传统url编码不同,所有getParameter 方法不能使用 setCharacterEncoding 无法解决输入项乱码问题
对于出现的乱码问题的几个针对解决:
1.使用get方式提交中文时 
<a href="/day21/downloadList?path=D:\TTPmusic\何晟铭\何晟铭 - 爱的供养.mp3">何晟铭 - 爱的供养.mp3</a><br/>
问题:IE6 提交后,服务器经过get乱码处理获得乱码 
原因:IE6对中文直接进行 get提交时,进行URL编码 ---- 编码发生问题 
解决:手动对get提交中文进行编码  ----- URLEncoder 
2.如果下载文件是中文名,设置 response.setHeader("Content-Disposition", "attachment;filename=" + filename); 出现附件名乱码
不同浏览器处理下载附件名乱码处理方式不同 ,例如 IE使用URL编码 、fireFox使用BASE64编码 
通过USER-AGENT 请求头信息字段,判断来访者浏览器类型 
注意:火狐浏览器在使用MimeUtility 进行Base64编码时存在问题 ,如果字符串中没有中文,无法进行编码 
解决:采用手动BASE64 编码 
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";

三实例:

public class UploadServlet extends HttpServlet{


DiskFileItemFactory factory=new DiskFileItemFactory();

ServletFileUpload upload=new ServletFileUpload(factory);

//判断提交表单的类型是否为multipart/form-data

    if(!upload.isMultipartContent(request))
    {
  return;
}

    try {
List list=upload.parseRequest(request);
Iterator it=list.iterator();

while(it.hasNext()){
  FileItem item=(FileItem)it.next();//每一个item就代表一个表单输出项

              if(item.isFormField())//判断input是否为普通表单输入项

String name=item.getFieldName();input的名称

String value= item.getString();input的值
}else{

得到上传文件的名称,并截取
String filename=item.getName();

得到上传文件要写入的目录
String path=this.getServletContext().getRealPath("/upload");
根据目录和文件创建输出流

FileOutputStream out=new FileOutputStream(path+filename);

InputStream in = item.getInputStream();
  byte buffer[] = new byte[1024];
 int len = 0;
while((len=in.read(buffer))>0){
  out.write(buffer,0,len);
    }
in.close();
out.close();
  }
}
} catch (FileUploadException e) 
{
e.printStackTrace();
   }
 }

}

四文件上传注意的细节问题

1.解决上传中文乱码问题 
可以通过upload.setHeaderEncoding("utf-8");


2.上传文件怎么保证服务器的安全?  (上传文件时不安全应用举例Runtime.getRuntime.exec("")可以执行DOS命令) 

解决方案:上传目录要禁止外界直接访问,一般的做法是把上传目录放到服务器的WEB-INF目录下.这个目录服务器是保护的,外界无法访问.


2.上传文件被覆盖的问题

服务器要为每一个上传文件生成一个唯一的文件名.可以使用UUID算法.

3.上传的文件需要打散

4.临时文件的删除

FileItemDelete.删除临时文件一定要在流关闭之后,否则会出现文件占用,而导致删除失败.

5.多文件上传问题:
主要是javascript编码,在页面动态添加文件上传项.

6.监听上传进度:

自己写一个监听器progressListener



0 0
原创粉丝点击