基于Struts2的单文件下载

 几乎所有人的人都下载过文件,如音频、视频、软件等等,在各类论坛、网站也会有相应信息导出的功能,那么这种下载的功能是如何分类的呢?又是如何实现的呢?

        对于第一个问题,我认为文件的下载分为两种:其一,信息动态生成,可能通过如时间节点、操作类型,而后导出相应的报表如txt、excel等;第二种,是下载现有文件(音视频、软件),这些文件通常会存储在相应的存储上,通过地址获得其字节流,而后下载。

        不管是第一种,还是第二种,都有一个特征,就是需要将信息转化为字节流,而后输出,这里阐述使用浏览器下载,即通过HTTP的相应报文进行下载。


一、下载的基本流程


        Request->File->Stream->Response

        下载的流程如上所述,用户发出一个下载的请求,而后,后台接收这个请求,对请求的文件或数据进行包装,在通过response返回给用户。那么按照此流程,来看个真实的例子:


1.1 Baidu云盘


         下面的截图,是在百度云空间下载文件时的request和response,可以看下其具体都有哪些信息:

        Content-Disposition:这是最重要的一个字段,意思是,当客户需要请求的信息以文件的形式返回时,设置此字                                            段,在rfc2616以及rfc1806中有详细的论述,其中一段e文原文为:
                                            The Content-Disposition response-header field has been proposed as a
                                            means for the origin server to suggest a default filename if the user
                                            requests that the content is saved to a file. This usage is derived
                                            from the definition of Content-Disposition in RFC 1806 [35].
                                            An example is:
                                           Content-Disposition:attachment; filename="fname.txt"
        Content-Length:此字段,表示返回内容的长度
        Content-Type:   此字段,表示返回的是何种类型的内容即MIME(媒体类型)

        这样,根据这三个字段,我们知道了文件的大小、文件的类型、以及何种操作,就可以将这个文件保存下来了。

1.2 HTTP方式文件下载的根基


        HTTP是应用层协议,并且HTTP协议选择了TCP协议作为其传输层协议,这样,也就保证了数据的可靠性。同时,这也是HTTP方式下载的根基,客户端与Server端建立了一条endpoint to endpoint的通道,用于传输信息,这条通道也是双向的。

二、Struts下载的实现


        注:本文不叙述Struts的搭建过程,文章中,使用的版本为,2.3.9;
        1th.查看Struts的帮助文档查看如下信息
        
         在Struts中每个action会对应一个result,上图是result type的类型,可以看出,对应file dowload的设置是Stream,看下Stream类型的详细配置为:

        可以看出,contentType、contentLength赫然在列,下面看下详细的操作
        注:以上文档信息,在struts2的官方doc中均可找到,有需要可在附件中下载

2.1 Struts文件下载的相关配置


       struts.xml
[html]  view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <!DOCTYPE struts PUBLIC   
  4.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
  5.     "http://struts.apache.org/dtds/struts-2.0.dtd">  
  6.   
  7.   
  8. <struts>  
  9.     <package name="a" extends="struts-default">         
  10.         <action name="download" class="com.hzy.struts2.download.FileDownLoad">  
  11.             <result name="success" type="stream">  
  12.                 <param name="contentLength">${fileLength}</param>  
  13.                 <param name="contentType">text/plain;charset=UTF-8</param>  
  14.                 <param name="contentDisposition">attachment;filename="${fileName}"</param>  
  15.                 <param name="inputName">inputStream</param>           
  16.             </result>  
  17.         </action>  
  18.           
  19.         <action name="downloadFile" class="com.hzy.struts2.download.FileDownLoadFile">  
  20.             <result name="success" type="stream">  
  21.                 <param name="contentType">application/octet-stream</param>  
  22.                 <param name="contentDisposition">attachment;filename="${fileName}"</param>  
  23.                 <param name="inputName">inputStream</param>   
  24.                 <param name="buffserSize">4096</param>        
  25.             </result>  
  26.         </action>  
  27.     </package>  
  28. </struts>  
         downloadFile.action:
[java]  view plain copy
  1. package com.hzy.struts2.download;  
  2.   
  3.   
  4. import java.io.InputStream;  
  5.   
  6. import org.apache.struts2.ServletActionContext;  
  7.   
  8. import com.opensymphony.xwork2.ActionSupport;  
  9.   
  10. public class FileDownLoadFile extends ActionSupport  
  11. {  
  12.       
  13.       
  14.     private String fileName;  
  15.     private InputStream inputStream;  
  16.       
  17.     public void setFileName( String fileName )  
  18.     {  
  19.         this.fileName = fileName + ".exe";  
  20.     }  
  21.   
  22.       
  23.     public String getFileName( )  
  24.     {  
  25.         return this.fileName;  
  26.     }  
  27.   
  28.       
  29.       
  30.     public InputStream getInputStream()  
  31.     {  
  32.         inputStream = ServletActionContext.getServletContext().getResourceAsStream( "/" + fileName );  
  33.           
  34.         if( inputStream == null )  
  35.         {  
  36.             System.out.println( "getResource error!" );  
  37.         }  
  38.         System.out.println( "FileName : " + fileName );  
  39.         return inputStream;  
  40.     }  
  41.       
  42.     @Override  
  43.     public String execute() throws Exception  
  44.     {  
  45.         return SUCCESS;  
  46.     }  
  47. }  
         download.action:
[java]  view plain copy
  1. package com.hzy.struts2.download;  
  2.   
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.InputStream;  
  5.   
  6. import com.opensymphony.xwork2.ActionSupport;  
  7.   
  8. public class FileDownLoad extends ActionSupport  
  9. {  
  10.       
  11.       
  12.     private String fileName;  
  13.     private int    fileLength;  
  14.       
  15.     public void setFileName( String start )  
  16.     {  
  17.         this.fileName = start;  
  18.     }  
  19.     public void setFileLength( int fileLength )  
  20.     {  
  21.         this.fileLength = fileLength;  
  22.     }  
  23.       
  24.     public String getFileName( )  
  25.     {  
  26.         return this.fileName;  
  27.     }  
  28.     public int getFileLength()  
  29.     {  
  30.         return this.fileLength;  
  31.     }  
  32.   
  33.       
  34.     public InputStream getInputStream()  
  35.     {  
  36.   
  37.         String content = "Hahahahaha : " + fileName;  
  38.           
  39.         this.setFileLength( content.getBytes().length );  
  40.         System.out.println( "The File Size : " + content.getBytes().length );  
  41.         return new ByteArrayInputStream( content.getBytes() );  
  42.     }  
  43.       
  44.     @Override  
  45.     public String execute() throws Exception  
  46.     {  
  47.         return SUCCESS;  
  48.     }  
  49. }  

              以上是,structs单文件下载的一个demo,download.acion模拟的是动态生成一些信息,然后通过stream流输出到前台,并以文本形式报文;downloadFile.action则是,下载服务器端的一个文件,这里下载的是Firefox.exe(20MB)的一个安装包。

       无论是哪种形式,都需要指定类型、长度大小等信息;在structs中这些关键的配置信息已经被固化到了struts.xml中,并且配置比较灵活。
       
       注:这里当下载Firxfox.exe时,并为指定content-Length,这里涉及到另一个协议,HTTP TRUNKED协议,该协议当content-Length未指定的时候,会对数据进行分片传输,并以0结尾,标示文件传输结束。对于该协议的具体细节将会单独开一篇讨论!

       同时,当文件大小不可知或未能明确给出时,会在http的响应报文中,给出Transfer-Encoding chunked字段;同时content-Length与Transfer-Encoding:chunked只能存在其一。

       下图是按上述demo做的截图,两个文件下载的访问方式如下(根据实际情况,酌情修改):
txt:

exe:


        下载文本:http://localhost:8080/Struts_DownFile_/download?fileName=abc
        下载文件:http://localhost:8080/Struts_DownFile_/downloadFile?fileName=Firefox
  

三、小结


        本文初次形成,比较粗糙,如struts缓冲区大小配置等并没有详细论述,而且文件下载一些拓展功能也并没叙述:批量文件下载、上传、断点下载、上传等;这些在后续的文章中会逐步补充,同时,每篇文章都会维护更新的,欢迎大家提出意见。
        诚挚感谢温大的文章,解决了我的困惑:http://my.oschina.net/u/866190/blog/170243

四、附件下载

Struts2(源码、框架、doc):http://pan.baidu.com/s/1gP1ct
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值