1. 程式人生 > >struts2檔案上傳和下載

struts2檔案上傳和下載

檔案的上傳和下載:
        a.使用apache組織開發的commons-fileupload和commons-io包,並且按需要配置fileUpload攔截器和相應的上傳引數,
            比如上傳檔案的型別,上傳檔案的大小。多檔案的上傳可以使用js程式碼來在頁面修改上傳檔案的列表,在Action中
            則用三個列表分別來儲存檔案物件(file),檔名(fileName),以及檔案型別(fileContentType)。
        b.檔案下載使用流進行讀取:return ServletActionContext.getServletContext.getResourceAsStream("檔名")

            並將Action的結果返回類設定為stream,即流。按需要配置相應的引數

struts2單檔案上傳:

首先是一個jsp檔案上傳頁面,這個比較簡單,就是一個表單,裡面有個檔案上傳框

複製程式碼
   <!--在進行檔案上傳時,表單提交方式一定要是post的方式,因為檔案上傳時二進位制檔案可能會很大,還有就是enctype屬性,這個屬性一定要寫成multipart/form-data,
  不然就會以二進位制文字上傳到伺服器端--> 
  <form action="fileUpload.action" method="post" enctype="multipart/form-data">
      
        username: <input 
type="text" name="username"><br> file: <input type="file" name="file"><br> <input type="submit" value="submit"> </form>
複製程式碼

接下來是FileUploadAction部分程式碼,因為struts2對上傳和下載都提供了很好的實習機制,所以在action這段我們只需要寫很少的程式碼就行:

複製程式碼
public class FileUploadAction extends
ActionSupport { private String username;    //注意,file並不是指前端jsp上傳過來的檔案本身,而是檔案上傳過來存放在臨時資料夾下面的檔案 private File file; //提交過來的file的名字 private String fileFileName; //提交過來的file的MIME型別 private String fileContentType; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public File getFile() { return file; } public void setFile(File file) { this.file = file; } public String getFileFileName() { return fileFileName; } public void setFileFileName(String fileFileName) { this.fileFileName = fileFileName; } public String getFileContentType() { return fileContentType; } public void setFileContentType(String fileContentType) { this.fileContentType = fileContentType; } @Override public String execute() throws Exception { String root = ServletActionContext.getServletContext().getRealPath("/upload"); InputStream is = new FileInputStream(file); OutputStream os = new FileOutputStream(new File(root, fileFileName)); System.out.println("fileFileName: " + fileFileName);     // 因為file是存放在臨時資料夾的檔案,我們可以將其檔名和檔案路徑打印出來,看和之前的fileFileName是否相同 System.out.println("file: " + file.getName()); System.out.println("file: " + file.getPath()); byte[] buffer = new byte[500]; int length = 0; while(-1 != (length = is.read(buffer, 0, buffer.length))) { os.write(buffer); } os.close(); is.close(); return SUCCESS; } }
複製程式碼

首先我們要清楚一點,這裡的file並不是真正指代jsp上傳過來的檔案,當檔案上傳過來時,struts2首先會尋找struts.multipart.saveDir(這個是在default.properties裡面有)這個name所指定的存放位置,我們可以新建一個struts.properties屬性檔案來指定這個臨時檔案存放位置,如果沒有指定,那麼檔案會存放在tomcat的apache-tomcat-7.0.29\work\Catalina\localhost\目錄下,然後我們可以指定檔案上傳後的存放位置,通過輸出流將其寫到流裡面就行了,這時我們就可以在資料夾裡看到我們上傳的檔案了。

檔案上傳後我們還需要將其下載下來,其實struts2的檔案下載原理很簡單,就是定義一個輸入流,然後將檔案寫到輸入流裡面就行,關鍵配置還是在struts.xml這個配置檔案裡配置:

FileDownloadAction程式碼如下:

複製程式碼
public class FileDownloadAction extends ActionSupport
{
    public InputStream getDownloadFile()
    {
        return ServletActionContext.getServletContext().getResourceAsStream("upload/通訊錄2012年9月4日.xls");
    }
    
    @Override
    public String execute() throws Exception
    {
        return SUCCESS;
    }
}
複製程式碼

我們看,這個action只是定義了一個輸入流,然後為其提供getter方法就行,接下來我們看看struts.xml的配置檔案:

        <action name="fileDownload" class="com.xiaoluo.struts2.FileDownloadAction">
            <result name="success" type="stream">
                <param name="contentDisposition">attachment;filename="通訊錄2012年9月4日.xls"</param>
                <param name="inputName">downloadFile</param>
            </result>
        </action>

struts.xml配置檔案有幾個地方我們要注意,首先是result的型別,以前我們定義一個action,result那裡我們基本上都不寫type屬性,因為其預設是請求轉發(dispatcher)的方式,除了這個屬性一般還有redirect(重定向)等這些值,在這裡因為我們用的是檔案下載,所以type一定要定義成stream型別,告訴action這是檔案下載的result,result元素裡面一般還有param子元素,這個是用來設定檔案下載時的引數,inputName這個屬性就是得到action中的檔案輸入流,名字一定要和action中的輸入流屬性名字相同,然後就是contentDisposition屬性,這個屬性一般用來指定我們希望通過怎麼樣的方式來處理下載的檔案,如果值是attachment,則會彈出一個下載框,讓使用者選擇是否下載,如果不設定這個值,那麼瀏覽器會首先檢視自己能否開啟下載的檔案,如果能,就會直接開啟所下載的檔案,(這當然不是我們所需要的),另外一個值就是filename這個就是檔案在下載時所提示的檔案下載名字。在配置完這些資訊後,我們就能過實現檔案的下載功能了。

struts2多檔案上傳:

其實多檔案上傳和單檔案上傳原理一樣,單檔案上傳過去的是單一的File,多檔案上傳過去的就是一個List<File>集合或者是一個File[]陣列,首先我們來看一下前端jsp部分的程式碼,這裡我用到了jquery來實現動態的新增檔案下載框以及動態的刪除下載框:

複製程式碼
    <script type="text/javascript" src="script/jquery-1.8.1.js"></script>
    <script type="text/javascript">
            
        $(function()
        {
            $("#button").click(function()
            {
                var html = $("<input type='file' name='file'>");
                var button = $("<input type='button' name='button' value='刪除'><br>");
                
                $("#body div").append(html).append(button);
                
                button.click(function()
                {
                    html.remove();
                    button.remove();
                })
            })
        })
    
    </script>
  </head>
  
  <body id="body">

    <form action="fileUpload2.action" method="post" enctype="multipart/form-data">
    
        username: <input type="text" name="username"><br>
        file: <input type="file" name="file">
        <input type="button" value="新增" id="button"><br>
        <div></div>
        <input type="submit" value="submit"> 
        
    </form>

  </body>
複製程式碼

file的名字必須都命名成file才行,然後處理多檔案上傳的action程式碼如下:

複製程式碼
public class FileUploadAction2 extends ActionSupport
{
    private String username;
    
  //這裡用List來存放上傳過來的檔案,file同樣指的是臨時資料夾中的臨時檔案,而不是真正上傳過來的檔案
    private List<File> file;
    
  //這個List存放的是檔案的名字,和List<File>中的檔案相對應
    private List<String> fileFileName;
    
    private List<String> fileContentType;

    public String getUsername()
    {
        return username;
    }

    public void setUsername(String username)
    {
        this.username = username;
    }

    public List<File> getFile()
    {
        return file;
    }

    public void setFile(List<File> file)
    {
        this.file = file;
    }

    public List<String> getFileFileName()
    {
        return fileFileName;
    }

    public void setFileFileName(List<String> fileFileName)
    {
        this.fileFileName = fileFileName;
    }

    public List<String> getFileContentType()
    {
        return fileContentType;
    }

    public void setFileContentType(List<String> fileContentType)
    {
        this.fileContentType = fileContentType;
    }
    
    @Override
    public String execute() throws Exception
    {
        String root = ServletActionContext.getServletContext().getRealPath("/upload");
        
        for(int i = 0; i < file.size(); i++)
        {
            InputStream is = new FileInputStream(file.get(i));
            
            OutputStream os = new FileOutputStream(new File(root, fileFileName.get(i)));
            
            byte[] buffer = new byte[500];
            
            @SuppressWarnings("unused")
            int length = 0;
            
            while(-1 != (length = is.read(buffer, 0, buffer.length)))
            {
                os.write(buffer);
            }
            
            os.close();
            is.close();
        }
        
        return SUCCESS;
    }
}
複製程式碼

這樣同樣將其寫到一個輸出流裡面,這樣我們就可以在資料夾裡看到上傳的多個檔案了

接下來的檔案下載就和剛才的檔案下載一模一樣,struts.xml也是一樣的,這裡就不再重複了

總結:總的來說,struts2提供的檔案上傳下載機制簡化了我們很多程式碼,我們可以在以後的專案中使用該機制,同樣我們也可以使用FileUpload元件來進行檔案的上傳,這個都是因個人愛好決定!