Struts1.x系列教程(15):使用DownloadAction类统计文件下载次数-阿里云开发者社区

开发者社区> 技术小胖子> 正文

Struts1.x系列教程(15):使用DownloadAction类统计文件下载次数

简介:
+关注继续查看
 除了标准的org.apache.struts.action.Action类外,在Struts中还提供了另外7Action类来完成特殊的工作。本文及后面的文章中将介绍这些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程序。这个程序的基本原理是当一个文件下载完成后,加这个文件在数据库中的下载次数加1,如果某个文件是第一次下载,则在数据库中添加一条新记录,下载次数为1
为了实现这个Web程序,需要如下几步:
  【第1步】建立用于保存文件下载次数的数据表

   在本例中我们使用名为struts数据库,并且在struts数据库中建立一个t_dcount表,代码如下:
  CREATE TABLE struts.t_dcount(
  id 
INT NOT NULL,
  
count INT NOT NULL,
  filename 
VARCHAR256 ) NOT NULL,
  
PRIMARY KEY (id)
  ) ENGINE 
= InnoDB  DEFAULT CHARSET=gbk;
【第2步】编写Struts动作类
这个Struts动作类负责完成文件的下载工作。如果在访问Struts动作类时不加file参数,会将指定目录下的所有文件(不包括隐藏文件)和已经下载的次数发送到客户端浏览器。如果通过file参数指定了下载文件,这个Struts动作就会下载这个文件。
    在<samples工程目录>\src\action目录中建立一个FileDownloadAction.java文件,代码如下:
  package chapter6.action;
  
  
import javax.servlet.http.*;
  
import org.apache.struts.action.*;
  
import org.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(
"com.mysql.jdbc.Driver");
              conn 
= DriverManager.getConnection(
                      
"jdbc:mysql://localhost/struts?characterEncoding=GBK",
                      
"root""1234");
          }
      }
      
// 获得某个文件的下载次数,其中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(1);
          }
          
return 0;
      }
      
// 在文件完成下载后,将该文件的下载次数加1
      private void incDownloadCount() throws Exception
      {
          openConnection();
          
int id = filename.hashCode();
          PreparedStatement pstmt 
= conn
                  .prepareStatement(
"UPDATE t_dcount SET count = count + 1 WHERE id = "
                          
+ String.valueOf(id));
          
if (pstmt.executeUpdate() == 0)
          {
              pstmt.executeUpdate(
"INSERT INTO t_dcount(id, count, filename) values("
                              
+ String.valueOf(id) + ",1,'" + 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 href='" + request.getContextPath() + mapping.getPath()
+ ".do?file=" + f.getName() + "'>" + f.getName()
                               
+ "</a>&nbsp;&nbsp;<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);
          }
      }
  }
【第3步】配置Struts动作类

    在struts-config.xml文件中的<action-mappings>标签中加入了如下内容:
<action path="/download" scope="request" type="action.FileDownloadAction" />
【第4步】配置下载路径    

在web.xml中找到一个叫action的Servlet,并在<servlet>标签中添加如下内容:
<init-param>
    <param-name>downloadPath</param-name>
    <param-value>D:\download\</param-value>
</init-param>
    读取可以设置自已的下载目录,但下载目录必须以“"”结尾。
    
启动Tomcat后,在IE中输入如下的URL来测试程序:

http://localhost:8080/samples/download.do




 本文转自 androidguy 51CTO博客,原文链接:http://blog.51cto.com/androidguy/214854,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
PHP-强制文件下载 (Force download)
在APACHE经过SSL加密后,原来下载文件(如XLS)的代码,在原来好用的情况下,出现“Internet Explorer 无法下载 **.php (来自**网站)。Internet Explorer无法打开该 internet 网站。
488 0
soufun使用次数统计,搜房网房源自动刷新程序 -- 测试版本,Dev.QQ 1205878060
soufun使用次数统计,搜房网房源自动刷新程序 -- 测试版本,Dev.QQ 1205878060  
611 0
struts2的文件上传
在做B/S系统时,通常会涉及到上传文件和下载文件,在没接struts2框架之前,我们都是使用apache下面的commons子项目的FileUpload组件来进行文件的上传,但是那样做的话,代码看起来比较繁琐,而且不灵活,在学习了struts2后,struts2为文件上传下载提供了更好的实现机制,在...
774 0
C# 使用FileUpload控件上传图片,将文件转换成二进制进行存储与读取
状况描述:   需要上传文件,但是不想要保存到实体路径下,便可以用该功能来实现。   效果图:      点击【Upload】按钮,上传文件到数据库;   点击【Preview】,预览文件;   具体实现:   前台: 1 2 3 4 : 5 ...
1683 0
首次曝光 | 阿里数万名开发者都在使用的数据库开发工具到底长什么样?
数据管理DMS(Data Management Service)是阿里巴巴自研图形化的数据库开发工具,已服务阿里巴巴及阿里云上几十万开发者实现安全便捷的数据库访问开发工作。用户可以通过DMS实现25种常见数据库的访问研发。
906 0
首次曝光 | 阿里数万名开发者都在使用的数据库开发工具到底长什么样?
数据管理DMS(Data Management Service)是阿里巴巴自研图形化的数据库开发工具,已服务阿里巴巴及阿里云上几十万开发者实现安全便捷的数据库访问开发工作。用户可以通过DMS实现25种常见数据库的访问研发。
1347 0
21119
文章
0
问答
文章排行榜
最热
最新