天天看點

struts2.0實作檔案上傳

首先,引入jar包。除了 Struts2.0的幾個核心jar包外,還需要額外引入commons-fileupload.jar和commons-io.jar。

引入這兩個包的時候,似乎版本也是一個比較重要的問題。我原先引入的是commons- fileupload-1.0.jar和commons-io.不知道那個版本.jar。代碼全部寫好之後卻報 java.lang.RuntimeException: Unable to load bean org.apache.struts2.dispatcher.multipart.MultiPartRequest (jakarta) - [unknown location]。這個class是在Struts1.0-core.jar包裡的,卻死活找不到。直到我把兩個包更新到了更高的版本,才算解決了這個 怪異的問題。

引入了jar包之後,寫action的代碼。主要的代碼來自網絡。可以忽略其中的log、 errorbean、baseaction等我自己寫的東西。

package common.web.action;

import java.io.*;

import java.util.Date;

import org.apache.struts2.ServletActionContext;

/**

* 實作檔案上傳的action

*/

public class UploadAction extends BasicAction {

private static final long serialVersionUID = 572146812454l;

// 輸入、輸出流的緩沖區大小

private int BUFFER_SIZE;

// 上傳檔案存儲路徑

private String filePath;

// 上傳檔案

// 注意,檔案上傳時<s:file/>同時與myFile,myFileContentType,myFileFileName綁定

// 是以同時要提供myFileContentType,myFileFileName的set方法

private File myFile;

// 上傳檔案類型

private String contentType;

// 上傳檔案名

private String fileName;

private String imageFileName;

// 檔案說明,與頁面屬性綁定

private String caption;

* 主要的方法,從請求中讀取檔案,複制到指定的路徑下去

@Override

public String execute() {

   log.info("上傳的檔案資訊:");

   log.info("檔案名: " + fileName+"; 檔案類型: " + contentType+"; 檔案大小: " + myFile.length() + " bytes");

   // 利用目前時間的毫秒數,加上原檔案的擴充名,構成新的檔案名

   imageFileName = new Date().getTime() + getExtention(fileName);

   log.info("新的檔案名為= " + imageFileName);

   log.info("新的檔案存儲路徑為= " + this.filePath);

   File imageFile;

   try {

    // 如果是絕對路徑

    if (filePath.indexOf(":") > 0) {

     imageFile = new File(this.filePath + "/" + imageFileName);

    } else {

     // 在工程路徑下的檔案夾中,根據新的檔案名,建立檔案

     imageFile = new File(ServletActionContext.getServletContext()

       .getRealPath(this.filePath)

       + "/" + imageFileName);

    }

   } catch (NullPointerException e) {

    e.printStackTrace();

    errorbean.setErrorMessage("找不到上傳檔案的儲存路徑!");

    errorbean.setMyException(e);

    errorbean.setSuccess(false);

    log.error(errorbean.toString());

    return INPUT;

   }

   // 将請求中的檔案複制到新的檔案中

   save(myFile, imageFile);

   errorbean.setSuccess(true);

   errorbean.setErrorMessage("檔案上傳成功!");

   if (errorbean.isSuccess()) {

    return SUCCESS;

   } else {

}

* 将請求中的檔案複制到指定路徑下去的方法;

* @param File

*            src: 源檔案

*            det: 目标檔案

private void save(File src, File dst) {

   // 輸入輸出流

   InputStream in = null;

   OutputStream out = null;

    // 根據源檔案和緩沖區大小,建立輸入流

    in = new BufferedInputStream(new FileInputStream(src), BUFFER_SIZE);

   } catch (Exception e) {

    errorbean.setErrorMessage("無法建立輸入流!");

    return;

    // 根據目标檔案和緩沖區大小,建立輸出流

    out = new BufferedOutputStream(new FileOutputStream(dst),

      BUFFER_SIZE);

    errorbean.setErrorMessage("無法建立輸出流!");

   } 

   // 從輸入流中讀取檔案,寫入輸出流中

   byte[] buffer = new byte[BUFFER_SIZE];

    while (in.read(buffer) > 0) {

     out.write(buffer);

   } catch (IOException e) {

    errorbean.setErrorMessage("從輸入流中讀取/向輸出流中寫入資料時發生異常!");

   } finally {

    try {

     // 關閉輸入輸出流

     if (null != in) {

      in.close();

     }

     if (null != out) {

      out.close();

    } catch (IOException e) {

     e.printStackTrace();

* 擷取上傳檔案擴充名的方法

* @param String

*            fileName:上傳檔案的全名

* @return String: 上傳檔案的擴充名

private String getExtention(String fileName) {

   int pos = fileName.lastIndexOf(".");

   return fileName.substring(pos);

* getter & setter

public void setMyFileContentType(String contentType) {

   this.contentType = contentType;

public void setMyFileFileName(String fileName) {

   this.fileName = fileName;

public void setMyFile(File myFile) {

   this.myFile = myFile;

public void setMyFile(String myFile) {

   System.out.println("String 類型的 myFile: "+myFile);

public String getImageFileName() {

   return imageFileName;

public String getCaption() {

   return caption;

public void setCaption(String caption) {

   this.caption = caption;

public void setBUFFER_SIZE(int buffer_size) {

   BUFFER_SIZE = buffer_size;

public int getBUFFER_SIZE() {

   return BUFFER_SIZE;

public void setFilePath(String filePath) {

   this.filePath = filePath;

jsp頁面的寫法如下。 <body>

   This is my JSP page for upload file.

   <br>

   <s:property value="errorbean.errorMessage"/>

   <s:form action="fileupload" namespace="/" method="POST" enctype="multipart/form-data">

    <s:file name="myFile" label="MyFile"></s:file>

    <s:textfield name="caption" label="Caption"></s:textfield>

    <s:submit label="submit"></s:submit>

   </s:form>

</body>

其中,enctype="multipart/form-data"是上傳檔案的form的寫法。如 果不這樣寫,action無法在Request裡面找到對應的file。并且,寫了這個東西最好配置上namespace。我最初隻寫 enctype="multipart/form-data"而沒寫namespace,結果又報 java.lang.RuntimeException: Unable to load bean org.apache.struts2.dispatcher.multipart.MultiPartRequest (jakarta) - [unknown location]。這個東西真是陰魂不散!不過加了namespace之後就沒事了。

struts.xml:

<action name="fileupload" class="UPLOAD">

    <interceptor-ref name="fileUpload">

     <param name="maximumSize">4194304</param>

     <param name="allowedTypes">

      image/jpeg,image/gif,image/jpg

     </param>

    </interceptor-ref>

    <interceptor-ref name="defaultStack" />

    <result name="success">test/upload.jsp</result>

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

   </action>

Struts.xml裡面的<interceptor-ref name="fileUpload">是為了限制上傳檔案的大小和檔案類型做的配置,配置的内容就是下面的兩個<param>标簽。在 這個過濾器之後一定要加上<interceptor-ref name="defaultStack" />,否則fileupload過濾到問題之後,不會轉到input結果中去,而仍然會向action中跳轉。這時讀取到的file就是null 了。此外,配置了這倆過濾器,就必須配置input結果,否則發生問題的時候找不到跳轉目标。

上面的例子是我測試通過了的。當然,檔案上傳還有一些尾巴工作可以改進,比如檔案存儲的臨時路徑、錯 誤提示資訊的國際化等等。這些另外再說吧!

本文轉自 斯然在天邊 51CTO部落格,原文連結:http://blog.51cto.com/winters1224/799053,如需轉載請自行聯系原作者