1.先给上传页面添加文件选择框标签。

[xhtml] view plaincopyprint?
<%@ page language="java" pageEncoding="UTF-8"%>  
<%@ taglib prefix="s" uri="/struts-tags"%>  
<%--  
=================================================================  
【控制台报告的关于POST的信息】  
当点击submit按钮时,在控制台中会弹出一下提示信息  
Struts has detected a file upload UI tag (s:file) being used   
without a form set to method 'POST'. This is probably an error!  
这是告诉我们当上传文件时,没有在<s:form/>中设定表单提交的method值为post  
事实上Struts2的<s:form/>表单已经默认的将method值设为post了  
如果我们讨厌这条信息的话,可以在<s:form/>中显式的指明method="POST"即可  
=================================================================  
【上传文件时的报错信息的国际化】  
展开struts2-core-2.0.11.jar中的org.apache.struts2包  
打开包中的struts-messages.properties文件,在该文件中发现了以下两个键  
struts.messages.error.file.too.large  
struts.messages.error.content.type.not.allowed  
然后再查看它们的键值,接着再与文件上传时所提示的错误消息对比一下  
这就为我们提供了给用户显示更为人性化错误信息的机会  
也就是说程序在运行中所自动产生的各种提示信息,都不是它自己随便产生出来的  
都是由Struts2在struts-messages.properties里面设置好的  
还有一个struts.messages.error.uploading属性也是和文件上传有关的  
比如在上传文件的过程中,突然网络中断,或者很多其它以外的情况  
所以struts.messages.error.uploading用来统一处理其它上传错误提示信息的  
=================================================================  
--%>  
<script type="text/javascript">  
    function addMore(){  
        var td = document.getElementById("more");  
        var br = document.createElement("br");  
        var input = document.createElement("input");  
        var button = document.createElement("input");  
        input.type = "file";  
        input.name = "upfile";  
        button.type = "button";  
        button.value = "Remove";  
        button.onclick = function(){  
            td.removeChild(br);  
            td.removeChild(input);  
            td.removeChild(button);  
        }  
        td.appendChild(br);  
        td.appendChild(input);  
        td.appendChild(button);  
}  
</script>  
  
<%--  
上传出错时产生的错误信息也是被放到FieldError中的  
所以就可以在页面中使用<s:fielderror/>输出错误消息  
--%>  
<s:fielderror/>  
  
<s:form action="upload" theme="simple" enctype="multipart/form-data">  
    <table border="9">  
        <tr>  
            <td>用户</td>  
            <td><s:textfield name="username"/></td>  
        </tr>  
        <tr>  
            <td>密码</td>  
            <td><s:password name="password"/></td>  
        </tr>  
        <tr>  
            <td>文件</td>  
            <td id="more"><s:file name="upfile"/><input type="button" value="Add More.." onclick="addMore()"></td>  
        </tr>  
        <tr>  
            <td> </td>  
            <td><s:submit value="上传"/></td>  
        </tr>  
    </table>  
</s:form>  

2.编写upLodeAction控制文件上传。

[java] view plaincopyprint?
package com.jadyer.action;  
  
import java.io.File;  
import java.io.FileInputStream;  
import java.io.FileOutputStream;  
import java.io.InputStream;  
import java.io.OutputStream;  
import java.util.List;  
  
import org.apache.struts2.ServletActionContext;  
  
import com.opensymphony.xwork2.ActionSupport;  
  
@SuppressWarnings("serial")  
public class UploadAction extends ActionSupport {  
    private String username;  
    private String password;  
    private List<File> upfile;  
    private List<String> upfileFileName;  
    private List<String> upfileContentType;  
      
    /* 五个属性相应的setter和getter方法略 */  
  
    @Override  
    public String execute() throws Exception {  
        for (int i = 0; i < upfile.size(); ++i) {  
            //获得第i个文件的输入流  
            //这里一定要用字节流,不要用字符流。因为上传过来的东西不知道是字节还是字符  
            InputStream is = new FileInputStream(upfile.get(i));  
            //指定路径  
            String root = ServletActionContext.getRequest().getRealPath("/upload");  
            File destFile = new File(root, this.getUpfileFileName().get(i));  
            //获得文件输出流  
            OutputStream os = new FileOutputStream(destFile);  
            //使用字节数组作为中间变量,完成输入到输出的转换  
            byte[] buffer = new byte[400];  
            int length = 0;  
            while ((length = is.read(buffer)) > 0) {  
                os.write(buffer, 0, length);  
            }  
            is.close();  
            os.close();  
        }  
        return SUCCESS;  
    }  
    /******************【关于org.apache.commons.io.FileUtils.copyFile()方法】*****************************/  
    //我们这里从前台标签接收到的文件域数量不定,所以定义为private List<File> upfile  
    //如果我们从前台表单接收到的文件域只有一个,可以定义为private File upfile  
    //此时就可以利用org.apache.commons.io.FileUtils.copyFile()方法,代码如下  
    //public class UploadAction extends ActionSupport {  
    //  private String username;  
    //  private String password;  
    //  private File upfile;  
    //  private String upfileFileName;  
    //  private String upfileContentType;  
    //  /* 五个属性相应的setter和getter方法略 */  
    //  @Override  
    //  public String execute() throws Exception {  
    //      String realpath = ServletActionContext.getServletContext().getRealPath("/upload");  
    //      File file = new File(realpath);  
    //      if(!file.exists()){  
    //          file.mkdirs();  
    //      }  
    //      FileUtils.copyFile(upfile, new File(file, upfileFileName));  
    //      return SUCCESS;  
    //  }  
    //}  
    /***************【文件上传的本质上就是IO操作】************************************************************/  
    //通过构造一个输入流,从upfile里面把文件的信息读到输入流里面去  
    //接着再把它写到一个输出流里面,这样就完成了文件的上传  
    /***************【Struts2的文件上传的实质】**************************************************************/  
    //Struts2虽然提供了文件上传的机制,但它并未实现文件上传底层的东西  
    //事实上Struts2是采用第三方的文件上传组件来帮助它完成上传的功能的  
    //它本身只是在更高层次上把它们封装了一下,以便于用户的开发和使用  
    //从这一点上来讲,Struts2跟Spring是非常类似的  
    //Spring的很多东西也是集成了第三方的东西,而它自己却并没有写多少  
    /***************【使用集合或数组实现多文件上传】***********************************************************/  
    //在Struts1中使用org.apache.struts.upload.FormFile类型来接收前台表单中的文件域  
    //在Struts2中使用java.io.File类型接收文件域,它的名字要与表单中的文件域的name值一致  
    //也可采用数组的方式声明upfile等等。实际从Struts2角度来看,它认为数组跟集合是没有区别的  
    //当它采用IOC的方式依赖注入的时候,它是同样对待数组和集合的,都是遍历其中的每一个元素  
    //不过还是建议大家采用集合加泛型的方式,这样可以使得程序更加简单,更加轻松明了  
    //而且,这里的三个集合中的元素的顺序都是一一对应的  
    //也就是说upfile集合的第一个文件对应upfileFileName集合的第一个名字,对应upfileContentType集合的第一个类型  
    //然后就可以很轻松的使用一个for循环读出全部的内容,然后写到系统的路径里面  
    //因此,我们就可以非常非常轻松的完成多文件上传的功能  
    /***************【定义文件上传所必备的三个属性】***********************************************************/  
    //文件在上传过来之后,必然会有它的相应的文件名和文件类型,然后在这里将它们接收过来  
    //Struts2中已为我们定义好了,它们前面的名字应与<s:file name=""/>的name值一致,后面分别跟FileName和ContentType  
    //所以,upfileFileName属性就是用来表示上传过来的文件的名字,upfileContentType属性就表示上传的文件的类型  
    //这些东西都是Struts2框架自动为我们注入进来的,非常类似于Spring里面的依赖注入  
    /***************【FileName和ContentType的固定写法】*****************************************************/  
    //打开struts2-core-2.0.11.jar中的struts-default.xml文件,然后观察  
    //发现Struts2默认使用的拦截器defaultStack中包含了fileUpload拦截器  
    //然后我们到org.apache.struts2.interceptor.FileUploadInterceptor类中查看  
    //在FileUploadInterceptor类中定义了一些属性,通过这些属性就可以限制上传文件的大小或类型等等  
    //然后在FileUploadInterceptor类源码的第253和254和255行可以发现两行代码。如下所示  
    //parameters.put(inputName, files);-----------------------------第253行  
    //parameters.put(inputName + "ContentType", contentType);-------第254行  
    //parameters.put(inputName + "FileName", fileName);-------------第255行  
    //这里inputName就是上传过来的文件的名字,然后在它的后面加上固定的ContentType和FileName  
    //关于文件上传,实际上我们只要知道在Action中应该定义三个必备的属性就可以了  
    //第一个属性就是upfile,它对应的是上传文件的文件体  
    //第二个属性就是upfileFileName,用来构造文件的名字  
    //第三个属性就是upfileContentType,用来构造文件的类型  
    /****************************************************************************************************/    
}  

3.配置Struts2的配置文件struts.xml

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"  
                        "http://struts.apache.org/dtds/struts-2.1.dtd">  
<struts>  
    <constant name="struts.multipart.saveDir" value="D:/"/>  
    <package name="struts2.1" extends="struts-default">  
        <action name="upload" class="com.jadyer.action.UploadAction">  
            <result name="success">/result.jsp</result>  
            <result name="input">/upload.jsp</result>  
            <interceptor-ref name="fileUpload">  
                <param name="maximumSize">512000</param>  
                <param name="allowedTypes">application/vnd.ms-powerpoint</param>  
            </interceptor-ref>  
            <interceptor-ref name="defaultStack"/>  
        </action>  
    </package>  
</struts>  

4.配置 web.xml

<?xml version="1.0" encoding="UTF-8"?>  
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
    <filter>  
        <filter-name>struts2</filter-name>  
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>struts2</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  
    <welcome-file-list>  
        <welcome-file>upload.jsp</welcome-file>  
    </welcome-file-list>  
</web-app>  

5.原贴地址  http://blog.csdn.net/jadyer/article/details/5889780

posted on 2012-06-01 16:25  一切都是幌子  阅读(958)  评论(0编辑  收藏  举报