一、上传下载实现原理
文件的上传下载实现原理,如图:
上传原理:
1、客户端浏览器通过文件浏览框,选择需要上传的文件内容(其中包括文件路径和文件内容)。
2、客户端浏览器通过上传按钮,将本地文件上传到浏览器。
3、服务器通过程序接收本地文件内容,并将其保存在服务器的磁盘中。
下载实现流程:
1、客户端浏览器通过点击下载按钮,将服务器保存的文件下载到本地磁盘。
2、服务器端通过程序将服务器文件响应给客户端。
二、文件的上传:
* 分析实现步骤: * 客户端浏览器通过文件域选择本地要上传的文件. * 点击"上传"按钮,将要上传的文件发送到服务器端. * 服务器端接收客户端发送的上传文件. * 定义一个保存上传文件的路径. * 将上传的文件保存在该路径中. * 将上传后的结果,响应给客户端浏览器. * 客户端: * 页面元素: * 定义一个用于向服务器端发送请求的表单. * 表单内具有文件域用于选择本地要上传的文件. * 表单内具有submit按钮用于提交请求的. * 问题: * 提交表单时,只是将文件域选择的文件名称上传.(并不是将上传文件提交) * 为表单设置enctype="multipart/form-data" * 注意: * 文件域必须指定name属性值,否则需要上传的文件数据是不会上传至服务器端. * 完成文件上传功能的表单的请求类型必须是POST方式. * 完成文件上传功能的表单的enctype属性值设置为“multipart/form-data”, 该值的作用是将需要上传的文件数据添加到Http请求体中,并使用MIME协议对上传的文件进行描述. * 服务器端: * 第三方工具:fileupload * 使用fileupload组件: * commons-fileupload-1.3.1.jar * commons-io-2.2.jar * 将该Jar包导入到Web工程中. * 注意的事情: * 将上传文件保存的目录放置在Web应用程序的根目录下.(不安全) * 问题描述: * 将上传文件保存后,可以通过浏览器访问到的. * 举例:如果上传的文件是一个JSP页面,包含Java代码(实现10秒自动关机). * 解决方案: * 将保存上传文件的目录,设置在一个不能通过浏览器访问的位置. * 将保存上传文件的目录,放置在"WEB-INF"目录下即可. * 处理上传的文件名称: * 问题描述: * 有些浏览器(IE 6),上传的文件名称并不是单纯的文件名,而是该文件的真实路径. * 解决方案: * 判断当前获取的文件名称是真实文件名,还是上传文件的真实路径. * 如果是真实路径,将文件名之前的所有路径去掉. // 文件名可能是绝对路径,进行切割 int index = fileName.lastIndexOf("\\"); // 获取"\"之后的内容(真正的文件名) if(index >= 0){ fileName = fileName.substring(index + 1); } * 处理上传文件的中文乱码问题: * 问题描述: * 上传文件的名称存在中文乱码问题. * 上传表单中的普通字段值存在中文乱码问题. * 解决方案: * 上传文件名称: * request.setCharacterEncoding("utf-8"); * ServletFileUpload.setHeaderEncdoing(“UTF-8”); * 普通字段值: * FileItem.getString(编码格式) - 编码格式:表示当前文本内容为什么编码. * 上传文件名称同名问题: * 问题描述: * 前后分别上传两个同名的文件,但内容不同. * 后上传的文件会覆盖前上传的文件. * 解决方案: * 生成唯一ID:UUID.randomUUID().toString()+"_"+fileName; * 一个目录不能存放多个文件: * 问题描述: * 如果一个目录中存在上传文件过多时,读取不方便. * 解决方案: * 分成多个目录存储上传文件: * 按照日期分目录:2015-03-31、2015-04-01等 * 按照MIME类型分目录:文本格式、图片、视频等 * 按照用户ID分目录:user1、user2等 * 使用UUID生成随机数的hashcode生成多级目录: * 限制单个文件上传大小:upload.setFileSizeMax(1024*1024*3); * 限制上传文件的总大小:upload.setSizeMax(1024*1024*10); * 文件缓存大小与临时目录 * 设置临时目录 * 默认的临时目录为System.getProperty("java.io.tmpdir"). * DiskFileItemFactory.setRepository(new File(getServletContext().getRealPath(临时目录相对路径))); * 在文件上传完成后,调用FileItem的Delete()方法,删除临时目录中的临时文件.(释放资源) * 设置缓存大小 * 如果不手动设置缓存大小,默认为10KB. * DiskFileItemFactory.setSizeThreshold(缓存字节数); * 手动将缓存大小设置10M,表示什么意思? * 如果上传文件小于10M的话,存在服务器端的内容中. * 如果上传文件大于10M的话,存在服务器端的临时目录中. * 注意:如果设置缓存大小过大,影响服务器端的性能. * 计算文件上传进度控制: * 计算上传进度的相关信息: * 已用时间:当前时间 – 开始时间 * 速度:已经上传大小 / 已用时间 * 剩余大小:总大小 – 已经上传大小 * 剩余时间:剩余大小 / 速度 * 如何实现监视上传进度: * 使用ServletFileUpload提供的setProgressListener()方法实现. * 实现多文件上传页面: * 分类: * 一个表单包含多个文件域. * 同时选择多个需要上传的文件,一起提交上传.(问题:要么一起成功,要么一起失败) * 一个文件域一个上传,多个上传文件之间是独立的.(Ajax技术:异步交互) * 多文件上传页面实现动态. * 文件的下载: * 问题: * 提供的下载页面,使用<a>链接指向要下载的资源文件. * 如果浏览器支持的格式,直接在浏览器中开发显示. * 如果浏览器不支持的格式,提供下载的选项(提供下载). * 现在的下载需求:无论下载文件的格式,浏览器是否支持,都需要下载选项. * 必须通过服务器端的Servlet来完成文件下载功能. * 如何使用文件下载: * 创建一个文件下载页面,当用户点击下载时,将请求提交服务器端的Servlet进行处理. * 服务器端的Servlet实现的步骤: * 获取客户端提交的下载文件名称. * 获取对应存储下载文件的目录结构. * 通过输入流读取对应下载文件内容. * 获取Response对象的OutputStream输出流. * 将读取的输入流,输出到Response对象的输出流,响应到客户端浏览器下载即可. * 问题: * 设置当前下载文件的MIME类型. response.setContentType(getServletContext().getMimeType(filename)); * 设置通知浏览器当前下载文件必须提供下载选项,而不是直接打开. response.setHeader("Content-Disposition", "attachment;filename="+filename); * 下载中文乱码问题: * 解决GET方式请求下载文件名的中文乱码: new String(filename.getBytes("ISO-8859-1"),"utf-8"); * 下载对应文件时,下载文件名称中文乱码: String userAgent = request.getHeader("User-Agent"); if(userAgent.contains("MSIE")){ // 表示当前是IE浏览器 filename = URLEncoder.encode(filename, "utf-8"); filename = filename.replace("+", " "); }else{ BASE64Encoder base64Encoder = new BASE64Encoder(); filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; }