一、文件上传
1.文件上传的实质是什么
文件的拷贝,文件从客户端拷贝服务器端
2.文件上传的工作
(1)客户端怎样将本地文件输出去?
1)文件上传的表单项 <input type=”file”>表单项必须有name属性值
2)文件上传必须是post提交方式
3)表单项中添加一个属性 enctype=“multipart/form-data”
(2)服务器怎样接受上传的文件,并将文件保存到服务器上?
注意:如果表单的enctype是multipart/form-data,那么通过request.getParameter等类似的方法都失效。虽然方法失效,但是request对象中仍然封装请求的数据。
获取多部分表单数据原理:
使用工具完成上文件文件表单项数据接收
Apache-Commons-fileupload工具可以很方便完成上传文件的接受工作
使用file-upload工具需要到两个jar
fileupload中常用API
磁盘文件项工厂:DiskFileItemFactory:设置文件上传一些参数
文件上传的核心类:ServletFileUpload:文件上传的核心类
文件项对象:FileItem:代表上传文件的表单中的每一部分
API进行详解
1 try { 2 //1、创建磁盘文件项工厂 3 DiskFileItemFactory factory = new DiskFileItemFactory(); 4 //2、创建文件上传的核心类 5 ServletFileUpload upload = new ServletFileUpload(factory); 6 //3、解析request获得表单项FileItem 7 List<FileItem> parseRequest = upload.parseRequest(request); 8 //4、判断是普通表单项还是文件上传项 9 for(FileItem item:parseRequest){ 10 //判读普通表单项还是文件上传项 11 boolean formField = item.isFormField();//判断是否是普通表单 true是普通表单 12 if(formField){ 13 //普通表单 14 //获得表单项的name属性值 15 String fieldName = item.getFieldName(); 16 //获得表单项的value值 17 String value = item.getString("UTF-8"); 18 19 System.out.println(fieldName+"----"+value); 20 }else{ 21 //文件上传项 22 //获得上传文件的名称 23 String fileName = item.getName(); 24 //获得上传文件的内容 25 InputStream in = item.getInputStream(); 26 //写到服务器端的磁盘上 27 //C:\Users\haohao\Desktop\apache-tomcat-7.0.53\webapps\day20_208\upload 28 String path = this.getServletContext().getRealPath("/upload"); 29 //C:\Users\haohao\Desktop\apache-tomcat-7.0.53\webapps\day20_208\upload\itcast.txt 30 OutputStream out = new FileOutputStream(path+"/"+fileName); 31 //文件拷贝的模板代码 32 int len = 0; 33 byte[] buffer = new byte[1024]; 34 while((len=in.read(buffer))>0){ 35 out.write(buffer, 0, len); 36 } 37 in.close(); 38 out.close(); 39 } 40 } 41 } catch (FileUploadException e) { 42 e.printStackTrace(); 43 }
(3)文件上传的细节
1)文件在上传时 会根据浏览器不同导致上传的文件的名称是不同
服务器端在item.getName() 获得上传文件的名称时会如下两种情况
有磁盘符 C:abcxxx.txt
没有磁盘符 xxx.txt
2)解决上传文件的重名的问题
解决方案:将上传文件的名称替换成随机uuid
例如:美女.jpg-----uuid.jpg
3)上传文件过多的问题
目录怎样去划分?
时间划分目录
区域划分目录
类型划分目录
按照算法进行目录划分
根据文件的hashcode
二、文件下载
1.文件下载实质
文件的拷贝,从服务器的磁盘上将文件拷贝本地客户端
2.文件下载的工作
(1)服务器端怎样将文件发送出去?
response.getOutputStream().write();
(2)客户端怎样接受服务器端传输的文件?
下载文件的过程是浏览器内核控制,不需要编码
3.问题:
文件什么情况下可以下载?
浏览器不识别文件都下载,识别的文件进行解析
什么情况下需要编写文件下载的代码?
浏览器可以识别的文件编写文件下载的代码
4.怎样在服务器端编写文件下载代码
步骤:
1)读取服务器磁盘上的文件
2)创建输出流写给客户端 response.getOutputStream()
3)告知客户端这个文件不需要解析 需要下载
Content-Type:文件类型MIME类型
获得MIME类型:getServletContext().getMimtType(文件名);
Content-Disposition:attachment;filename=文件名称
5.关于下载中文文件
发现中文文件在下载时不能正常显示文件名称
问题出现在 attachment;filename=中文文件名称
怎样对要下载的中文名称进行编码?
if(火狐){
对下载中文文件名使用base64编码
}else if(ie){
对下载中文文件名使用UTF-8编码
}
1 //获取filename 2 String filename = request.getParameter("filename");//???? 3 //解决get提交的中文乱码问题 4 filename = new String(filename.getBytes("iso8859-1"),"UTF-8");//美女.jpg 5 6 String downloadFilename = filename; 7 String agent = request.getHeader("User-Agent"); 8 if (agent.contains("MSIE")) { 9 // IE浏览器 10 downloadFilename = URLEncoder.encode(filename, "utf-8"); 11 downloadFilename = filename.replace("+", " "); 12 } else if (agent.contains("Firefox")) { 13 // 火狐浏览器 14 BASE64Encoder base64Encoder = new BASE64Encoder(); 15 downloadFilename = "=?utf-8?B?" 16 + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; 17 } else { 18 // 其它浏览器 19 downloadFilename = URLEncoder.encode(filename, "utf-8"); 20 21 } 22 23 //response.setHeader("Content-Disposition","attachment;filename=" + new String(filename.getBytes("gbk"), "ISO8859-1")); 24 25 26 //设置两个头通知客户端要进行文件的下载 27 response.setContentType(this.getServletContext().getMimeType(filename)); 28 response.setHeader("Content-Disposition", "attachment;filename="+downloadFilename);//问题:给客户端的filename乱码 29 30 //编写文件下载的代码 31 String path = this.getServletContext().getRealPath("/download/"+filename); 32 InputStream in = new FileInputStream(path); 33 OutputStream out = response.getOutputStream(); 34 int len = 0; 35 byte[] buffer = new byte[1024]; 36 while((len=in.read(buffer))>0){ 37 out.write(buffer, 0, len); 38 } 39 in.close(); 40 }
不同浏览器默认对下载文件名称解码方式不同,导致客户端在编码时要进行判断
火狐是什么解码方式:base64
ie是什么解码方式:UTF-8