servlet文件上传

需要的组件

   Commons-fileupload*.jar组件和Commons-io*.jar组件

  form表单中使用属性enctype指定数据发送到服务器上时浏览器使用的编码类型,默认为:application/x-www-form-urlencoded当 enctype="multipart/form-data";时 传输时会以二进制传输数据

要点:

   org.apache.commons.fileupload.FileItem;

         在上传组件中普通的表单域和文件域都被看成一个个的FileItem

   org.apache.commons.fileupload.disk.DiskFileItemFactory;

         创建FileItem对象的工厂,这个工厂类中可以配置存缓冲区大小和存放临时文件的目录

   org.apache.commons.fileupload.servlet.ServletFileUpload

         负责处理上传的文件数据,并将每部分的数据封装到FileItem对象中

request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
try {
//判断上传的类型是否是 enctype="multipart/form-data" true是 false表示不是
boolean flag=ServletFileUpload.isMultipartContent(request);
if(flag){
/*
* 创建生产FileItem的DiskFileItemFactory工厂的实例
* * 设置内存缓冲区的大小
* * 设置文件存放的临时路径
*/
DiskFileItemFactory facoty=new DiskFileItemFactory();
//设置内存缓冲区的大小
int sizeThreshold=3*1024*1024;
facoty.setSizeThreshold(sizeThreshold);
//设置文件存放的临时路径
facoty.setRepository(new File("D:/temp"));
//创建ServletFileUpload实例,工厂作为参数
ServletFileUpload upload=new ServletFileUpload(facoty);
//设置上传文件的大小,如果上传文件大于设置的大小,则要手动抛出SizeLimitExceededException 异常
long sizeMax=83*1024*1024;
upload.setSizeMax(sizeMax);

//解析request请求,返回集合[集合中存放FileItem]
List<FileItem> items=upload.parseRequest(request);
Iterator<FileItem> it=items.iterator();
while(it.hasNext()){
FileItem item=it.next();

//如果是普通的表单域
if(item.isFormField()){
// <input type="text" name="fileName" value="xx" >
String fieldName=item.getFieldName(); //普通的表单域name属性的值
//获得文本域中的内容时要注意转码,中文会出现中文乱码
// String value=new String(item.getString().getBytes("utf-8");
String filedValue=item.getString(); //普通的表单域value属性的值
System.out.println(fieldName + " "+filedValue);

}else{
//如果是文件域 <input type="file"
String fieldName=item.getFieldName(); //文件域name属性的值
String fileName=item.getName(); //文件域value属性的值
String contentType=item.getContentType(); //上传文件的类型
boolean isInMemory =item.isInMemory(); //true:来自内存,false:来自内存和硬盘
long size=item.getSize(); //上传文件的字节数
System.out.println(fieldName +" "+fileName +" "+contentType+" "+isInMemory+" "+size);
//获取文件的后缀名(如果没有后缀名lastIndexOf(".")=-1 )
if(fileName.lastIndexOf(".")!=-1){
String ext=fileName.substring(fileName.lastIndexOf(".")+1);
//设置允许上传的文件格式
String allowExt[]={jpg,zip,doc,jpeg,png,gif};
//检测扩展名是否在数组中
List<String> list=Arrays.asList(allowExt);
if(!list.contains(ext)){
throw new RuntimeException("您上传的文件扩展名不允许");
}

}else{
throw new RuntimeException("您上传的文件没有扩展名,不允许上传");
}
//获取保存上传文件的路径
String realpath=this.getServletContext().getRealPath("/upload");
//方法一获取文件名:
//fileName=fileName.substring(fileName.lastIndexOf("\\")+1);
//方法二获取文件名:
File file=new File(fileName);
fileName=file.getName();
System.out.println("截取后的文件名 "+fileName);
//保存上传文件
item.write(new File(realpath+"/"+fileName));
}
}
}
}catch(SizeLimitExceededException e){
e.printStackTrace();
throw new RuntimeException("上传文件的大小不能超过3M");
}
catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}

文件下载

request.setCharacterEncoding("utf-8");

String filename=request.getParameter("filename");
System.out.println("filename "+filename);

/**通过response.setHeader("content-Type", "application/x-msdownload")这个头,
* Web服务器需要告诉浏览器其所输出的内容的类型不是普通的文本文件或 HTML 文件,而是一个要保存到本地的下载文件
*/
response.setContentType("application/x-msdownload");
/** 该报头指定了接收程序处理数据内容的方式,在HTTP应用中只有attachment 是标准方式,
* attachment 表示要求用户干预。
* 在 attachment 后面还可以指定 filename 参数,该参数是服务器建议浏览器将实体内容保存到文件中的文件名称。
* 在设置 Content-Dispostion 之前一定要指定 Content-Type.
*/
response.setHeader("Content-Disposition", "attachment;filename="+java.net.URLEncoder.encode(filename,"utf-8"));
//获取下载文件的真实路径
String realPath=this.getServletContext().getRealPath("/upload");
filename=realPath+"/"+filename;

//创建文件输入流
FileInputStream fis=new FileInputStream(filename);
//创建缓冲输入流
BufferedInputStream bis=new BufferedInputStream(fis);
//获取响应的输出流
OutputStream os=response.getOutputStream();
//创建缓冲输出流
BufferedOutputStream bos=new BufferedOutputStream(os);

//把输入流的数据写入到输出流
byte[] b=new byte[1024];
int len=0;
while((len=bis.read(b))!=-1){
bos.write(b, 0, len);
}
bos.close();
bis.close();