文件上传的流程
- 使用Apache文件上传组件DiskFileItemFactory,然后可以得到解析器,设置临时文件夹的目录,设置单个文件夹大小的最大值,设置上传文件总量的最大值,包括所有文件的表单的总和.
- ServletFileUpload.isMultipartContent(request):判断是普通表单,还是带文件上传的表单,即要判断客户端<form>标记的enctype属性是enctype="multipart/form-data".如果是普通输入项的数据,接下来完成对request的解析,如果fileItem封装的是普通输入项的数据,getFieldName返回表单标签的name属性,还要解决普通输入项的数据的中文乱码问题.如果是上传文件,用FileItem类的getName()方法获得文件上传字段的文件名.
- 不同浏览器提交的文件名不一样,有些浏览器提交上来的文件名是带有路径的,有些只是文件名 处理获取到的上传文件的文件名的路径部分,获取上传文件的输出流,创建一个缓冲区,循环将输入流写到缓冲区中,并使用FileOutPutStream输出流将缓冲区中的数据写入到指定的目录
- 关闭输入输出流
文件下载
- 获取要下载的文件的绝对路径
- 获取要下载的文件名
- 针对IE或者以IE为内核的浏览器进行处理,再对反面进行处理
- 设置content-disposition响应头控制浏览器以下载的方式打开文件
- 获取要下载的文件输入流
- 创建缓冲区
- 通过response对象获取OutPutStream输出流对象
- 将FileInputStream流写入到buffer缓冲区
- 关闭输入输出流
注意事项
在文件名中含有中文编码时,设置响应头时需要用URLEncoder.encode(fileName, “UTF-8”)文件输出流最好使用OutPutStream,避免使用PrintWriter.因为字节流对象可以处理任意类型的数据,而字符流输出对象只能处理字符数据,若用字符流处理字节流数据,会导致数据丢失.
注意:
1、在文件名中含有中文编码时,设置响应头时需要使用URLEncoder.encode(fileName, “UTF-8”)方法进行编码,否则容易出现中文乱码的情况。
2、文件输出流对象应尽量使用OutputStream流对象,避免使用PrintWriter流对象。因为OutputStream是字节流对象,可以处理任意类型的数据;而PrintWriter是字符流输出对象,只能处理字符数据,如果用字符流处理字节数据,就会导致数据丢失。
public class LoadServlet extends HttpServlet{
/**
* 载文件,通过OutputStream输出流
*/
public void doPost(HttpServletRequest request,HttpServletResponse response){
//1.获取要下载的文件的绝对路径
String realPath = this.getServletContext().getRealPath("/load/ceshi.txt");
//2.获取要下载的文件名
String fileName = realPath.subString(realPath.lastIndexOf("\\")+1);
String userAgent = request.getHeader("User-Agent");
//针对IE或者以IE为内核的浏览器:
if (userAgent.contains("MSIE")||userAgent.contains("Trident")) {
fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
} else {
//非IE浏览器的处理:
fileName = new String(fileName.getBytes("UTF-8"),"ISO-8859-1");
}
//3.设置content-disposition响应头控制浏览器以下载的方式打开文件
response.setHeader("content-disposition","attachment;filename="+fileName);
//4.获取要下载的文件输入流
InputStream in = new FileInputStream(realPath);
int len = 0;
//5.创建书缓冲区
byte[] buffer = new byte[1024];
//6.通过response对象获取OutputStream输出流对象
OutputStream os = response.getOutputStream();
//7.将FileInputStream流对象写入到buffer缓冲区
while((len=in.read(buffer))>0){
os.write(buffer,0,len);
}
//8.关闭流
in.close();
os.close();
}
}
public void upFile(){
request.setCharacterEncoding("utf-8");
//使用Apache文件上传组件
DiskFileItemFactory factory=new DiskFileItemFactory();
//得到了解析器
ServletFileUpload servletFileUpload=new ServletFileUpload(factory);
//判断上传是文件还是表单
boolean result=servletFileUpload.isMultipartContent(request);
System.out.print(result);
Date date=new Date();
String file_name=null;
String file_desc=null;
String autoName=new SimpleDateFormat("yyyyMMddHHmmss").format(date);
System.out.print(autoName);
String username=String.valueOf(request.getSession().getAttribute("loginuser"));
if(result){
try{
List<FileItem> fileitems=null;
fileitems=servletFileUpload.parseRequest(request);
System.out.println(autoName+"----------------------------------------------"+username);
for(FileItem fileitem:fileitems){
//相当于表单元素的input里的name属性
if(fileitem.isFormField()){
String fieldname=fileitem.getFieldName();
String value=fileitem.getString("utf-8");
//解决代码乱码的问题
if("file_name".equals(fieldname)){
file_name=value;
}else if("file_desc".equals(fieldname)){
file_desc=value;
}
}else{
InputStream inputStream=fileitem.getInputStream();
if(inputStream!=null&&inputStream.available()>0){
//得到文件名
String filename=fileitem.getName();
//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
filename=filename.substring(filename.lastIndexof("\\")+1);
int index=filename.lastIndexOf(".");
String ext=filename.substring(index);
//String ext=filename.substring(filename.lastIndexof(".")+1);
System.out.print(filename+" "+ext);
autoName+=ext;
String path=getServletContext().getRealPath("/uploadfile");
System.out.println(path+"89999999999999999999999");
File file=new File(path,autoName);
System.out.println(file+"3456789-------------");
//得到一个输出流,输出到服务器的磁盘
FileOutputStream outputStream=new FileOutputStream(file);
//一次上传1kb,创建一个缓冲区
byte[]datas=new byte[1024];
//判断输入流中的数据是否已经读完的标识
int len=0;
//循环将输入流读入到缓冲区中,(len=in.read(buffer))>0就表示in里面还有数据
while((len=inputStream.read(datas))>0){
//读进多少字节,就写出多少字节
//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
outputStream.write(datas,0,len);
}
//关闭输入流
inputStream.close();
outputStream.flush();
//关闭输出流
outputStream.close();
}
}
}
}catch(FileUploadException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//调用service层的方法把相应的数据写到数据库
FileServiceImpl service=new FileServiceImpl();
int t=service.addfile(file_name,file_desc,autoName,username);
if(t>0){
response.getWriter().print("<script>alert('上传成功!'); location.href='FileServlet?p=doma';</script>");
}
}