Struts2下多文件的上傳與下載

 

Struts2下多文件的上傳與下載

目錄

關鍵詞... 1

寫在前面... 1

需求... 1

環境... 2

目錄結構... 3

重要文件的看點... 3

web.xml. 3

struts.xml. 4

UploadAction. 5

DownloadAction. 8

UploadConfigurationRead. 10

工程結果截圖... 13

提供原代碼下載... 14

 

關鍵詞

多文件 上傳 下載 隨意文件 java Struts2 單例 配置 動態讀取 李順利 

 

寫在前面

    在網絡上,對於Java處理文件上傳和下載的技術比較多,而Struts作爲一款優秀的框架也提供了非常方便的文件上傳和下載,而網上的一些例程都非常的不全面,概括來:

1)   文件上傳比較多,多文件上傳少一點

2)   文件下載很少的,看似簡單,實則不然

3)   文件下載一般都是單文件或者固定的文件,並沒有(很少)實現隨意文件的下載的例子

最近也在研究一下文件的上傳和下載,在整合網上、浪曦風中葉老師和自己的學習的思想,寫了這個工程,提供給大家參考,所以的代碼終在IE、FireFox、Chrome測試通過。

 

需求

1.能夠對多個文件進行上傳(可以選擇上傳文件個數,也即上傳文件個數不定)

2.能夠對上傳路徑進行配置文件(upload.properties)指定,使用了一些類似單例模式的靜態代碼塊

3.對配置文件中的路徑可以進行動態讀取(不重啓服務器)

4.Struts2進行下載處理,能對上傳的所有文件進行下載(多個)

5.文件保存的名稱UUID生成,不過顯示並下載的名稱都是原文件名稱

(人性化,通過UploadFiles處理)

 

環境

最新的Struts2:struts-2.1.8、MyEclipse、Tomcat、IE、FireFox、Chrome

 

目錄結構

clip_image001

 

重要文件的看點

web.xml

    <filter>

        <filter-name>struts2</filter-name>

        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>

    </filter>

    在web.xml中使用了最新的Struts2的中央處理器類org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter,而不再是以前的org.apache.struts2.dispatcher.FilterDispatcher,FilterDispatcher在新版本Struts2中已經標註爲過時了,請大家儘量使用最新的filter。

 

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

    <constant name="struts.i18n.encoding" value="utf8" />

    <package name="file" namespace="/" extends="struts-default">

       <action name="showUpload">

           <result>/upload.jsp</result>

       </action>

       <action name="upload" class="org.usc.file.UploadAction">

           <result name="input">/upload.jsp</result>

<!--          <result name="success">/upload_success.jsp</result>-->

           <result name="success">/download.jsp</result>

           <interceptor-ref name="fileUpload">

<!--大家可以設置成自己的配置,想文件類型和大小等限制          -->

<!--              <param name="maximumSize">2097152</param>單位是字節   2M  (2097152B)       -->

<!--              <param name="allowedTypes">image/bmp,image/x-png,image/png,image/gif,image/jpeg,image/jpg,image/pjpeg</param>-->

<!--              -->

<!--                 容許文件類型爲doc,ppt,xls,pdf,txt,java-->

<!--              -->

           </interceptor-ref>

           <interceptor-ref name="defaultStack"></interceptor-ref>

       </action>

 

       <action name="download" class="org.usc.file.DownloadAction">

           <result name="success" type="stream">

              <param name="contentDisposition">attachment;filename="${fileName}"</param>

              <param name="inputName">downloadFile</param>

           </result>

       </action>

    </package>

</struts>

 

就是文件上傳和下載的一些Struts2配置,注意上傳的時候,請引入

<interceptor-ref name="defaultStack"></interceptor-ref>,

下載的配置中注意:<param name="inputName">downloadFile</param>

其他的配置解釋網上很多,不懂的可以先google學習一下。

 

UploadAction

在此文件中請注意文件數組的使用,因爲是多文件

 

package org.usc.file;

import java.io.File;

import java.util.ArrayList;

import java.util.List;

import java.util.UUID;

import org.apache.commons.io.FileUtils;

import org.apache.struts2.ServletActionContext;

import org.usc.utils.UploadConfigurationRead;

import com.opensymphony.xwork2.ActionSupport;

 

/**

 * 多文件上傳類

 *

 * @author MZ

 *

 * @Time 2009-11-24下午09:26:44

 */

public class UploadAction extends ActionSupport

{

 

    /**

     *

     */

    private static final long serialVersionUID = 1L;

    private File[] upload;// 實際上傳文件

    private String[] uploadContentType; // 文件的內容類型

    private String[] uploadFileName; // 上傳文件名

    private List<UploadFiles> uploadFiles = new ArrayList<UploadFiles>();

 

    public String execute() throws Exception

    {

       try

       {

           String targetDirectory = ServletActionContext.getServletContext()

                  .getRealPath("/"+ UploadConfigurationRead.getInstance().getConfigItem("uploadFilePath").trim());// 獲得路徑

           for (int i = 0; i < upload.length; i++)

           {

              String fileName = uploadFileName[i];// 上傳的文件名

              String type = uploadContentType[i];// 文件類型

              String realName = UUID.randomUUID().toString()+ getExt(fileName);// 保存的文件名稱,使用UUID+後綴進行保存

 

              File target = new File(targetDirectory, realName);

              FileUtils.copyFile(upload[i], target);// 上傳至服務器的目錄,一般都這樣操作,

                                                 // 在把路徑寫入數據庫即可

 

              UploadFiles uf = new UploadFiles();// 創建文件

              uf.setUploadContentType(type);

              uf.setUploadFileName(fileName);

              uf.setUploadRealName(realName);

 

              uploadFiles.add(uf);// 添加到需要下載文件的List集合中

 

          

           }

           ServletActionContext.getRequest().setAttribute("uploadFiles",

                  uploadFiles);

 

       } catch (Exception e)

       {

           e.printStackTrace();

           addActionError(e.getMessage());

 

           return INPUT;

       }

 

       return SUCCESS;

 

    }

 

    public File[] getUpload()

    {

       return upload;

    }

 

    public void setUpload(File[] upload)

    {

       this.upload = upload;

    }

 

    public String[] getUploadContentType()

    {

       return uploadContentType;

    }

 

    public void setUploadContentType(String[] uploadContentType)

    {

       this.uploadContentType = uploadContentType;

    }

 

    public String[] getUploadFileName()

    {

       return uploadFileName;

    }

 

    public void setUploadFileName(String[] uploadFileName)

    {

       this.uploadFileName = uploadFileName;

    }

 

    public static String getExt(String fileName)

    {

       return fileName.substring(fileName.lastIndexOf("."));

    }

 

}

 

 

 

DownloadAction

在此文件中要注意public InputStream getDownloadFile()的名稱在Struts2配置文件配置,返回的是一個InputStream類型的對象。

 

package org.usc.file;

 

import java.io.InputStream;

import java.io.UnsupportedEncodingException;

import com.opensymphony.xwork2.ActionSupport;

import org.apache.struts2.ServletActionContext;

import org.usc.utils.UploadConfigurationRead;

 

public class DownloadAction extends ActionSupport

{

    private static final long serialVersionUID = 6329383258366253255L;

    private String fileName;

    private String fileRealName;

    public void setFileName()

    {

       // 得到請求下載的文件名

       String fname = ServletActionContext.getRequest().getParameter("name");

       String frealname = ServletActionContext.getRequest().getParameter("realname");

       try

       {

           /*

            * 對fname參數進行UTF-8解碼,注意:實際進行UTF-8解碼時會使用本地編碼,本機爲GBK。

            * 這裏使用request.setCharacterEncoding解碼無效.

            * 只有解碼了getDownloadFile()方法才能在下載目錄下正確找到請求的文件

            */

           fname = new String(fname.getBytes("ISO-8859-1"), "UTF-8");

           frealname= new String(frealname.getBytes("ISO-8859-1"), "UTF-8");

       } catch (Exception e)

       {

           e.printStackTrace();

       }

       this.fileName = fname;

       this.fileRealName = frealname;

//     System.out.println(fileName);

//     System.out.println(fileRealName);

    }

 

    /*

     * @getFileName 此方法對應的是struts.xml文件中的: <param

     * name="contentDisposition">attachment;filename="${fileName}"</param>

     * 這個屬性設置的是下載工具下載文件時顯示的文件名, 要想正確的顯示中文文件名,我們需要對fileName再次編碼

     * 否則中文名文件將出現亂碼,或無法下載的情況

     */

    public String getFileName() throws UnsupportedEncodingException

    {

 

       fileRealName = new String(fileRealName.getBytes(), "ISO-8859-1");

 

       return fileRealName;

    }

 

    /*

     * @getDownloadFile 此方法對應的是struts.xml文件中的: <param

     * name="inputName">downloadFile</param> 返回下載文件的流,可以參看struts2的源碼

     */

    public InputStream getDownloadFile()

    {

 

       this.setFileName();

       return ServletActionContext.getServletContext().getResourceAsStream("/"+UploadConfigurationRead.getInstance().getConfigItem("uploadFilePath").trim()+"/" + fileName);

    }

 

    @Override

    public String execute() throws Exception

    {

       return SUCCESS;

    }

}

UploadConfigurationRead

動態讀取配置文件,借鑑網上的代碼

 

package org.usc.utils;

import java.io.File;

import java.io.FileInputStream;

import java.net.URI;

import java.net.URISyntaxException;

import java.util.Properties;

/**

 * 動態讀取配置文件類

 *

 * @author MZ

 *

 * @Time 2009-11-24下午08:25:22

 */

public class UploadConfigurationRead {

 

    /**

     * 屬性文件全名,需要的時候請重新配置PFILE

     */

    private static String PFILE = "upload.properties";

 

    /**

     * 配置文件路徑

     */

    private URI uri = null;

 

    /**

     * 屬性文件所對應的屬性對象變量

     */

    private long m_lastModifiedTime = 0;

 

    /**

     * 對應於屬性文件的文件對象變量

     */

    private File m_file = null;

 

    /**

     * 屬性文件所對應的屬性對象變量

     */

    private Properties m_props = null;

 

    /**

     * 唯一實例

     */

    private static UploadConfigurationRead m_instance = new UploadConfigurationRead();

 

    /**

     * 私有構造函數

     *

     * @throws URISyntaxException

     */

    private UploadConfigurationRead() {

       try {

           m_lastModifiedTime = getFile().lastModified();

           if (m_lastModifiedTime == 0) {

              System.err.println(PFILE + "file does not exist!");

           }

           m_props = new Properties();

           m_props.load(new FileInputStream(getFile()));

 

       } catch (URISyntaxException e) {

           System.err.println(PFILE+"文件路徑不正確");

           e.printStackTrace();

       } catch (Exception e) {

           System.err.println(PFILE+"文件讀取異常");

           e.printStackTrace();

       }

    }

 

    /**

     * 查找ClassPath路徑獲取文件

     *

     * @return File對象

     * @throws URISyntaxException

     */

 

    private File getFile() throws URISyntaxException {

       URI fileUri = this.getClass().getClassLoader().getResource(PFILE).toURI();

       m_file = new File(fileUri);

       return m_file;

    }

 

    /**

     * 靜態工廠方法

     *

     * @return 返回ConfigurationRead的單一實例

     */

    public synchronized static UploadConfigurationRead getInstance() {

       return m_instance;

    }

 

    /**

     * 讀取一特定的屬性項

     */

    public String getConfigItem(String name, String defaultVal) {

       long newTime = m_file.lastModified();

       // 檢查屬性文件是否被修改

       if (newTime == 0) {

           // 屬性文件不存在

           if (m_lastModifiedTime == 0) {

              System.err.println(PFILE + " file does not exist!");

           } else {

              System.err.println(PFILE + " file was deleted!!");

           }

           return defaultVal;

       } else if (newTime > m_lastModifiedTime) {

           m_props.clear();

           try {

              m_props.load(new FileInputStream(getFile()));

           } catch (Exception e) {

              System.err.println("文件重新讀取異常");

              e.printStackTrace();

           }

       }

       m_lastModifiedTime = newTime;

       String val = m_props.getProperty(name);

       if (val == null) {

           return defaultVal;

       } else {

           return val;

       }

    }

 

    /**

     * 讀取一特定的屬性項

     *

     * @param name

     *            屬性項的項名

     * @return 屬性項的值(如此項存在), 空(如此項不存在)

     */

    public String getConfigItem(String name) {

       return getConfigItem(name, "");

    }

 

}

 

 

工程結果截圖

在IE(遨遊)中多文件上傳

clip_image003

在IE(遨遊)中多文件下載

clip_image005

在Firefox中多文件上傳

clip_image007

在Firefox中多文件下載

clip_image009

在Chrome中多文件上傳

clip_image011

在Chrome中多文件下載

clip_image013

服務器中所以文件

clip_image015

提供原代碼下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章