程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Struts1.x系列教程(15):使用DownloadAction類統計文件下載次數

Struts1.x系列教程(15):使用DownloadAction類統計文件下載次數

編輯:關於JAVA

除了標准的org.apache.struts.action.Action類外,在Struts中還提供了另外7個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程序。這個程序的基本原理是當一個文件下載完成後,加這個文件在數據庫中的下載次數加1,如果某個文件是第一次下載,則在數據庫中添加一條新記錄,下載次數為1。

為了實現這個Web程序,需要如下幾步:

【第1步】建立用於保存文件下載次數的數據表

在本例中我們使用名為struts數據庫,並且在struts數據庫中建立一個t_dcount表,代碼如下:

CREATE TABLE struts.t_dcount(
id INT NOT NULL,
count INT NOT NULL,
filename VARCHAR( 256 ) 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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved