​文件上传与下载

简介

  文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到本地。

  对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,struts上传的功能就是基于这个实现的。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。

文件上传

  1、文件上传页面和消息提示页面

  • 为方便用户处理文件上传数据,Apache 开源组织提供了一个用来处理表单文件上传的一个开源组件( Commons-fileupload ),该组件性能优异,并且其 API 使用极其简单,可以让开发人员轻松实现 web 文件上传功能,因此在 web 开发中实现文件上传功能,通常使用 Commons-fileupload 组件实现。
  • 使用 Commons-fileupload 组件实现文件上传,需要导入该组件相应的支撑 jar 包: Commons-fileupload 和 commons-io。commons-io 不属于文件上传组件的开发 jar 文件,但 Commons-fileupload 组件从1.1 版本开始,它工作时需要 commons-io 包的支持。

  upload.jsp页面的代码如下:

在文件上传的页面要用enctype="multipart/form-data" method="post"来表示进行文件上传。

2、处理文件上传的Servlet

​ 

3、文件上传的细节

  上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的:

  (1)、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。

  (2)、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。

  (3)、为防止一个目录下面出现太多文件,要使用hash算法打散存储。

  (4)、要限制上传文件的最大值。

  (5)、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。

  • 乱码问题
    • 上传文件名乱码:servletFileupload.setHeaderEncoding("utf-8") —— 乱码解决问题一
    • 表单普通项乱码:fileItem.getString("utf-8") —— 乱码解决问题二
  • 临时文件删除

必须先关闭 FileItem 的输入流,再调用 FileItem.delete ()方法 删除临时文件。

  • 上传文件保存目录

首先应该明白一个概念:web 工程中 WEB-INF 在浏览器端不允许通过 URL 直接访问。

    • WEB-INF内 :必须通过服务器端程序去访问,Servlet ---- getRealPath(/WEB-INF) ---------------- 需要权限,需要身份认证
    • WEB-INF外 :浏览器直接通过URL访问 ------------------ 任何人都可以访问
    • 思考:假设有个电影会员点播网站,可以付费在线看电影。那么上传电影应该放到哪里? 答案:WEB-INF 里面,客户端不能直接访问。再分析:淘宝里的商家上传商品图片,商品图片应该放在哪里?答案: WEB-INF 外面,客户端可以直接访问。
  • 文件覆盖

假设客户端上传的所有文件都放到同一个目录中,当文件名重名时,会发生文件覆盖,如何解决?答案:文件名唯一。

    • // 保证上传文件名唯一
    • filename = UUID.randomUUID().toString() + filename;
  • 多目录分散

当上传文件很多时,如果不对文件分散到不同目录去,那就会集中在同一个目录中,这样访问某个文件需要很长时间,甚至不响应,查找困难,所以应该采用目录分散算法,有如下几种目录分散算法:

    • 按时间 —— 比如一天一个目录
    • 按用户 —— 比如淘宝某个商家上传的所有商品图片都放在一个单独目录
    • 每个目录存放固定数量文件 —— 每个目录存放1000个文件,每次上传文件时判断目录中文件是否超过1000,若超过则新建一个目录,保存在新目录中

web 应用中实现文件下载的两种方式:

  • 方式一:超链接直接指向下载资源

这时将使用 DefaultServlet ,它会将资源返回,如果浏览器对该资源不支持直接打开(比如说 Excel 文档),则会询问用户是否下载,如果浏览器识别下载文件格式,则会自动打开(比如说图片)

  • 方式二:编写程序实现下载,这时这时需设置两个响应头,需要要符合 Mime 协议

设置 Content-Type 的值为:下载文件所对应 MIME 类型、 web 服务器希望浏览器不直接处理相应的实体内容,而是由用户选择将相应的实体内容保存到一个文件中,这就需要设置 Content-Disposition (以附件形式传输),在设置 Content-Dispostion 之前一定要指定 Content-Type。

注意:ServletContext.getMimeType(file) 可以得到下载资源所对应的 Mime 类型,你也可以在 tomcat/conf/web.xml 文件中查询各种 MIME 类型。

  • 为了获得服务器的资源,应该提供资源的绝对磁盘路径,这里有两种方式:
    • File.getAbsolutePath() --返回此抽象路径名的绝对路径名字符串,不唯一
    • FIle.getCanonicalPath() -- 返回返回此抽象路径名的规范路径名字符串,唯一
    • 通过比较可以发现,下面一种写法更加符合规范,推荐使用。
  • 请求的乱码问题

在深度优先搜索的 jsp 示例中,注意如下的写法:

  String args = URLEncoder.encode(f.getCanonicalPath(),"utf-8");

意义:get、post 方式访问,会使用 URL 编码,而目录有可能含有中文,如果不进行 utf-8 编码,则可能会根据不同的浏览器而报错。

  • 响应的乱码问题

在文件下载时,点击链接会弹出下载框,如果不进行处理,则资源名存在乱码问题,在本文的《9、文件下载概述》中有如下代码:

    • // 设置响应头
    • response.setContentType(getServletContext().getMimeType(file));// 根据文件扩展名获得MIME类型
    • // 等级于 response.setHeader("Content-Type",xxx);
    • response
    • .setHeader("Content-Disposition", "attachment;filename=" + file);// 以附件下载

注意:不同的浏览器对于响应的编码方式有所不同,比如 IE 采用 URL 编码,火狐采用该 base64 编码。

再思考,如何根据不同的浏览器选择合适的编码方式呢?很显然,只要我们知道了当前客户端是什么浏览器就可以 if - else 判断,然后执行不同的编码方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值