关于文件下载

一、什么是文件下载
首先,什么是文件?
我的理解,对于计算机世界而言,文件是数据存储的基本单位,是计算机硬件存储数据的软件抽象。对于软件层面的数据存储而言,任何表现的数据存储本质上都是文件。
其次,什么是下载?
我的理解,下载是数据传输的方式之一,计算机的数据可以有很多的传输方式,可以通过数据线拷贝到硬盘,可以通过打印机输出到A4纸,也可以将一台机器上的数据通过网络上传到某一个服务器,也可以从服务器下载数据到客户端等,所以我觉得这里的拷贝、打印、上传、下载本质上都是一样的,区别可能就是通道不一样,目的地不一样等。将好比是同样是从A地到B地,我们可以说是打的、坐公交、驾车、步行、坐地铁等。

二、浏览器下载
总所周知,浏览器是通过请求(request)和响应(response)和服务器的交互的,实际上我们可以将服务器的每一次response都看成是一次下载,只是下载下来的内容有的浏览器自己打开(html,img等),有的需要借助其他的工具打开(word,excel等),有的浏览器无法打开也不需要借助其他软件打开,而是提示用户是否保存该文件,我们今天要探讨的就是第三种情况,为了方便起见,我们以下所说的下载特指第三种情况。

三、MIME类型
在说浏览器下载之前,先来了解一下MIME类型。
MIME的英文全称是"Multipurpose Internet Mail Extensions" 多功能Internet 邮件扩充服务,它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。服务器会将它们发送的多媒体数据的类型告诉浏览器,而通知手段就是说明该多媒体数据的MIME类型,从而让浏览器知道接收到的信息哪些是MP3文件,哪些是Shockwave文件等等。服务器将MIME标志符放入传送的数据中来告诉浏览器使用哪种插件读取相关文件。
常见的MIME类型(通用型):   
超文本标记语言文本 .html text/html   
xml文档 .xml text/xml   
XHTML文档 .xhtml application/xhtml+xml   
普通文本 .txt text/plain   
RTF文本 .rtf application/rtf   
PDF文档 .pdf application/pdf   
Microsoft Word文件 .word application/msword   
PNG图像 .png image/png   
GIF图形 .gif image/gif   
JPEG图形 .jpeg,.jpg image/jpeg   
au声音文件 .au audio/basic   
MIDI音乐文件 mid,.midi audio/midi,audio/x-midi   
RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio   
MPEG文件 .mpg,.mpeg video/mpeg   
AVI文件 .avi video/x-msvideo   
GZIP文件 .gz application/x-gzip   
TAR文件 .tar application/x-tar   
任意的二进制数据 application/octet-stream
(参考百度百科)
简单的说MIME类型就是response告诉浏览器返回的文件类型。

四、response对象的contenttype属性
Response对象有一个叫contenttype的属性,它定义服务器发送给客户端内容的MIME类型。

response.setContentType("application/octet-stream");

我们知道,在网页编程中我们有时将超链接指向一个Word或Excel文件,当用户点击这个链接时浏览器会自动调用对应方法将这个文件打开。之所以能做到这点就是因为用户机器上安装office后会在浏览器中注册对应的MIME资源类型。比如说word文件的MIME类型是Application/msword(前者是MIME类型,后者是MIME子类),Excel文件的MIME资源类型是Application/msexcel。

事实上,凡是浏览器能处理的所有资源都有对应的MIME资源类型,比如说html文件的MIME类型是Text/html,JPG文件的MIME类型是Image/JPG。
在与服务器的交互中,浏览器就是根据所接受数据的MIME类型来判断要进行什么样的处理,对html、JPG等文件浏览器直接将其打开,对Word、Excel等浏览器自身不能打开的文件则调用相应方法打开。对没有标记MIME类型的文件,浏览器则根据其扩展名和文件内容猜测其类型。如果浏览器无法猜出,则将它作为application/octet-stream。要了解各种文件的MIME类型,请在win98 我的电脑->查看->文件夹选项->文件类型 中查看。

五、attachment和inline
通过以上学习,我们了解到浏览器是通过response对象的contenttype处理响应文件的,那么对于浏览器不能打开的文件,其实浏览器还是有两个选择,一是以上所说的提示用户保存或者调用用户安装的软件打开,二是浏览器无论如何都会尝试将其打开。
到底是选择哪种方式,浏览器是通过response的header属性中的attachment和inline
判断的。

//提示用户保存
response.addHeader("Content-Disposition","attachment;filename=" + fn);


//浏览器无论如何尝试打开
response.addHeader("Content-Disposition","inline;filename=" + fn);


六、文件下载的实现方式
方式一:直接网页上做超级链接,如:

[url=download/jre-windows-i586.exe]点击下载[/url]

不难理解,如果我们的servlet容器没有对*.exe的请求拦截处理,servlet容器会创建request请求对象,读取指定目录下的资源,然后通过response对象返回到客户端浏览器,
此时的response的contenttype的MIME类型可能是servlet容器通过文件后缀名自己设置的,我们可以通过一些http抓包工具进行查看。
这种实现下载的方式很简单,因为servlet容器为我们做了一切事情,但是这样服务器上的目录资源会直接暴露给最终用户,会给网站带来一些不安全的因素。

方式二:基于第一种方式的不安全性,我们可以将servlet容器帮我们做的事情自己来做。即,客户端不直接访问我们服务器的资源目录,而是访问我的一个servlet(jsp,Action等),我们自己去读取资源,然后通过response对象返回给客户端。

public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{

HttpServletResponse response = (HttpServletResponse)res;

File file = new File("path");
// 取得文件名。
String filename = file.getName();

// 以流的形式下载文件。
InputStream fis = new BufferedInputStream(new FileInputStream("path"));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();

// 清空response, 设置response的Header
response.reset();
response.addHeader("Content-Disposition",
"attachment;filename=" + new String(filename.getBytes()));
response.addHeader("Content-Length", "" + file.length());
response.setContentType("application/octet-stream");

OutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(buffer);
out.flush();
out.close();
}

我了解的文件下载方式大致就这两种,很多文章所说的local本地下载,url远程下载,RequestDispatcher下载等方式本质上都是通过设置response对象输出流到客户端,并且设置response的contenttype、header等,万变不离其宗,二进制流的来源可以是任意地方、框架对response的封装等导致文件下载有很多的表现形式。
我们只需要抓住本质,举一反三,触类旁通即可。
参考文章:
[url]http://jeff312.iteye.com/blog/494065[/url]
[url]http://www.189works.com/article-42222-1.html[/url]
[url]http://www.cnblogs.com/zyxzhsh/archive/2010/12/02/1894089.html[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值