Struts1.x系列教程(15):使用DownloadAction类统计文件下载次数
除了标准的 apache struts action Action类外 在Struts中还提供了另外 个Action类来完成特殊的工作 本文及后面的文章中将介绍这些Action类的用法
一 DownloadAction类简介
可能有时需要在Web程序中加入下载功能 如果要下载的是静态文件 可以直接交给Web服务器处理 但如果要对下载的文件做额外的功能 如统计文件的下载次数 就需要在下载文件之前先要调用相应的程序进行处理
虽然我们可以直接在Action子类中来处理下载文件 但是如果这样的程序比较多时 就会写很多重复的代码 为了简化这个工作 Struts提供了一个新的Action类 DownloadAction 所有继承了DownloadAction类的Struts动作都可以非常容易地完成下载文件的工作
DownloadAction类有一个抽象方法getStreamInfo 这个方法的定义如下
protected abstract StreamInfo getStreamInfo(ActionMapping mapping ActionForm form HttpServletRequest request HttpServletResponse response) throws Exception;
getStreamInfo方法返回一个StreamInfo对象 StreamInfo接口是DownloadAction类的一个内部接口 这个接口的定义如下
public static interface StreamInfo { public abstract String getContentType(); public abstract InputStream getInputStream() throws IOException;}
从上面的代码可以看出 StreamInfo接口有两个方法 其中getInputStream方法返回了服务端要下载的文件的InputStream对象 getContenttType方法返回了HTTP响应消息头字段Content Type的信息 在getStreamInfo方法中只要返回了实现这两个方法的StreamInfo对象 就可以自动完成下载工作
为了方便起见 DownloadAction类中还提供了两个实现StreamInfo的内类 FileStreamInfo和ResourceStreamInfo 这两个类的构造方法的定义如下
public FileStreamInfo(String contentType File file); public ResourceStreamInfo(String contentType ServletContext context String path);
我们可以使用FileStreamInfo类来下载静态的文件 如果要下载的文件在Web根目录 可以使用ResourceStreamInfo类 其中path参数表示文件相对于Web根目录的路径 必须以 / 开头 表示从Web根目录开始
二 实例 统计文件的下载次数
在本节中将使用DownloadAction类实现一个统计文件下载次数的Web程序 这个程序的基本原理是当一个文件下载完成后 加这个文件在数据库中的下载次数加 如果某个文件是第一次下载 则在数据库中添加一条新记录 下载次数为
为了实现这个Web程序 需要如下几步
第 步 建立用于保存文件下载次数的数据表
在本例中我们使用名为struts数据库 并且在struts数据库中建立一个t_dcount表 代码如下
CREATE TABLE struts t_dcount( id INT NOT NULL count INT NOT NULL filename VARCHAR( ) NOT NULL PRIMARY KEY (id) ) ENGINE = InnoDB DEFAULT CHARSET=gbk;
第 步 编写Struts动作类
这个Struts动作类负责完成文件的下载工作 如果在访问Struts动作类时不加file参数 会将指定目录下的所有文件(不包括隐藏文件)和已经下载的次数发送到客户端浏览器 如果通过file参数指定了下载文件 这个Struts动作就会下载这个文件
在<samples工程目录>\src\action目录中建立一个FileDownloadAction java文件 代码如下
package chapter action; import javax servlet ; import apache struts action ; import apache struts actions ; import java io ; import java sql ; public class FileDownloadAction extends DownloadAction { private Connection conn; private String path; private String filename; // 获得了Connection对象 private void openConnection() throws Exception { if (conn == null) { Class forName( mysql jdbc Driver ); conn = DriverManager getConnection( jdbc:mysql://localhost/strutscharacterEncoding=GBK root ); } } // 获得某个文件的下载次数 其中id是文件名的hashcode private int getDownloadCount(int id) throws Exception { openConnection(); PreparedStatement pstmt = conn prepareStatement( SELECT count FROM t_dcount WHERE id = + String valueOf(id)); ResultSet rs = pstmt executeQuery(); while (rs next()) { return rs getInt( ); } return ; } // 在文件完成下载后 将该文件的下载次数加 private void incDownloadCount() throws Exception { openConnection(); int id = filename hashCode(); PreparedStatement pstmt = conn prepareStatement( UPDATE t_dcount SET count = count + WHERE id = + String valueOf(id)); if (pstmt executeUpdate() == ) { pstmt executeUpdate( INSERT INTO t_dcount(id count filename) values( + String valueOf(id) + + filename + ) ); } } // 下载文件时调用getStreamInfo方法 protected StreamInfo getStreamInfo(ActionMapping mapping ActionForm form HttpServletRequest request HttpServletResponse response) throws Exception { final FileInputStream fis = new FileInputStream(path + filename); final String contentType = application/file ; // 建议设置content disposition响应信息头 否则Web浏览器在下载文件时 // 无法在保存文件对话框中显示正确的文件名 response setHeader( content disposition attachment; filename= + filename); incDownloadCount(); return new DownloadAction StreamInfo() // 使用隐式的方法实现了StreamInfo接口 { public String getContentType() { return contentType; } public InputStream getInputStream() throws IOException { return fis; } }; } // 如果Struts动作不加file请求参数 则通过execute方法将指定目录中文件列表输出到客户端 public ActionForward execute(ActionMapping mapping ActionForm form HttpServletRequest request HttpServletResponse response) throws Exception { path = this getServlet() getInitParameter( downloadPath ); filename = request getParameter( file ); if (filename == null) { File file = new File(path); File[] files = file listFiles(); response setCharacterEncoding( GBK ); PrintWriter out = response getWriter(); out println( <ul> ); for (File f : files) // 开始向客户端浏览器输出文件列表 { if (f isFile() && !f isHidden()) { out println( <li><a + request getContextPath() + mapping getPath()+ dofile= + f getName() + > + f getName() + </a> <font color= blue >下载次数 + String valueOf(getDownloadCount(f getName() hashCode())) + </color></li> ); } } out println( </ul> ); return null; } else { // 当file参数存在时 则调用DownloadAction中的execute方法 // 实际上 在DownloadAction类中的execute方法调用了getStreamInfo方法 // 这条语句就相当于调用了getStreamInfo方法 return super execute(mapping form request response); } } }
第 步 配置Struts动作类
在struts config xml文件中的<action mappings>标签中加入了如下内容
<action path= /download scope= request type= action FileDownloadAction />
第 步 配置下载路径
在web xml中找到一个叫action的Servlet 并在<servlet>标签中添加如下内容
<init param> <param name>downloadPath</param name> <param value>D:\download\</param value></init param>
读取可以设置自已的下载目录 但下载目录必须以 结尾
启动Tomcat后 在IE中输入如下的URL来测试程序
lishixinzhi/Article/program/Java/ky/201311/28413
离线下载是无限次数的
但你每回添加的文件不能超过离线下载的空间数,比如刚开通是1级,离线下载是10G空间,你每次添加的文件数不能超过10G大小,可以等这次添加的文件下载完后再添加其他的文件,比如这次添加1到30集,等这些下载完后将原来的1到30级删除后再添加31到60级。离线下载关闭电脑后会自动的在迅雷服务器里下载,一直到完成任务为止。
使用FTP、使用HTTP。
1、使用FTP:可以在服务器上安装FTP服务器软件,然后让客户端电脑通过FTP客户端软件连接到服务器。
2、使用HTTP:可以将要下载的文件放在Web服务器上,然后让客户端使用浏览器下载所需的文件。
0条评论