zoukankan      html  css  js  c++  java
  • 笔记02 文件上传、文件下载、类型转换器、国际化的支持

    Struts2的上传

    1. Struts2默认采用了apache commons-fileupload 

    2. Struts2支持三种类型的上传组件 

    3. 需要引入commons-fileupload相关依赖包

       * commons-io-1.3.2.jar

       * commons-fileupload-1.2.1.jar

    4. 表单中需要采用POST提交方式,编码类型需要使用:multipart/form-data

    5. Struts2的Action

        取得文件名称->>规则:输入域的名称+固定字符串"FileName"String类型。

        取得文件数据->>规则:File 输入域的名称,File类型。

        取得内容类型->>规则:输入域的名称+固定字符串"ContentType"String类型。

         <form action="testUpload.action" method="post" enctype="multipart/form-data">

               <input type="file" name="file">

               <input type="submit" value="upload">

         </form>

         private File file;//文件对应页面name名称

         private String fileContentType;//文件类型

         private String fileFileName;//文件名称 

    6. 得到输入流,采用输出流写文件(action中方法):

        public String execute() throws Exception {

               InputStream is = null;

               OutputStream os = null;

               try {

                      is = new BufferedInputStream(new FileInputStream(myFile));

                      os = new BufferedOutputStream(new FileOutputStream("c:\" + myFileFileName));

                      byte[] buffer = new byte[1024];

                      int len = 0;

                      while ((len = is.read(buffer)) > 0) {

                                  os.write(buffer, 0, len);

                      }

                 }finally {

                      if (is != null) {is.close();}

                      if (os != null) {os.close();}

                 }

                 return Action.SUCCESS;

             }

    7. 文件上传:配置拦截器

        在配置上传文件大小时要配置常量:(设置上传大小,需要配置两个地方)

        <!-- 配置上传大小 -->关注

        <constant name="struts.multipart.maxSize" ="20971520"></constant>

                <interceptor-ref name="fileUpload">

                       <param name="maximumSize">20971520</param>上传大小

                       <param name="allowedTypes">image/jpeg,image/gif,image/bmp</param>允许类型

                </interceptor-ref>

          注意:若自己加拦截器,必须配置默认拦截器栈,且默认拦截器放在后面。

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

    8. 1). 文件上传:设置不允许上传的文件类型,不使用fileupload的拦截器

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

                   <action name="testUpload" class="com.bjpowernode.action.TestAction" method="upload">

                          <result>/index.jsp</result>

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

                          <param name="notAllowedTypes">image/jpeg,image/jpg</param>           // 关注

                   </action>         

             </package>

        2). 通过方法判断:

             public String filterDocType(String[] types){

                           //获取文件类型

                           String fileType = this.getFileContentType();

                           //遍历类型

                           for(String type:types){

                                    if(type.equals(fileType))

                                            return INPUT;

                            }

                            return null;

               } 

       3). 文件上传时先判断类型:

            public String upload() throws IOException{                

                      String filterResult = this.filterDocType(this.getNotAllowedTypes().split(","));关注

                      if(filterResult!=null){                                  //关注

                                  ActionContext.getContext().put("typeError","类型上传不允许");

                                  return filterResult;

                      }

                    (看第6个,第6个代码)

                    上传文件代码......

        

           (上传数据库过程中可以为文件设置新名称等)

           //使用日期作为新名称

           String u = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());

            //获取扩展名称

            String exename = this.fileFileName.substring(fileFileName.lastIndexOf("."));

            t_picture.setOldName(fileFileName);

            String newname = u+exename;

            t_picture.setNewName("upload/"+newname);

            //将数据存入数据库

            dao.save(user);

            //文件数据输入流

            InputStream in = new FileInputStream(file);

            //上传后文件存放的路径

            String path = ServletActionContext.getServletContext().getRealPath("/upload");        

        }  

        说明:     

        a保存文件时应该保存上传的文件名称和真正存放时的文件名称。

        b. 可以一次有多个上传框一起上传文件。多文件上传文本框名字必须一样,放在同一个form里面。action中定义一个数组,名字为上传文件文本框的名字。

        c. 默认上传大小为2M。

        d. struts:将文件保存到saveDir目录下,然后从该目录下以IO的形式读到指定的目录下。所以file指向的是saveDir目录下的文件。文件file.getName()得到的是文件在缓存中的名字,也就是saveDir下的名字。

    文件下载:

    1. 配置文件中result的类型必须<result type="stream">

    2. 配置属性:        

    复制代码
    <action name="testDownload" class="com.bjpowernode.action.TestAction" method="download">
    
               <result type="stream">
    
                       <!-- 表示强制弹出提示框,下载的文件(包含路径) -->
    
                        //通过el表达式,动态的获得下载时下载框显示的名字。
                        //attachment表示不管能不能打开,都要打开下载对话框。默认为内联,就是浏览器能打开就打开
    
                        <param name="contentDisposition">attachment;filename=${filename}</param>
    
                        <!-- 在类中要有一个get方法来对应inputStream,且返回类型为inputStream -->
    
                        //action中对应的方法名get+里面的参数名(如:download对应的是getDownload)
    
                        //inputName是固定的
                       <param name="inputName">download</param>                       
    
                       <!-- 文件下载的大小 -->
    
                      <param name="bufferSize">1024</param>
    
                 </result>
    
                 <result name="input">/error.jsp</result>  
                 
    </action>        
    复制代码

    3. 错误:java.lang.IllegalArgumentException: Can not find a java.io.InputStream with the name [inputStream] in the invocation stack. Check the <param name="inputName">

         第一个原因:<param name="inputName">inputStream</param>在类中没有对应的public InputStream getInputStream()方法

         第二种原因:文件不存在

         第三种原因:文件的路径不对        

    4. 文件下载需要写的两个方法(action)

         /**

          * 文件下载

          */

         public String download(){

                return SUCCESS;

         }

         /**

            * 文件下载流,返回值必须是InputStream

            * filename必须包含完整的文件路径。filename是从web项目开始,向下的路径。如:webroot下有一个upload里,放着下载的文件。

            

            */

           public InputStream getInputStream(){

                      return ServletActionContext.getServletContext().getResourceAsStream(filename);

            }

    5. 不同的action之间跳转,可以在配置文件中设置<result type="redirectAction">testShow</result>,推荐使用  redirectAction

    Struts2的类型转换器

    1. 如何实现Struts2的类型转换器?

        * 类型转换器必须继承DefaultTypeConverter,一般继承它的子类StrutsTypeConverter。action中调用set和  get方法时,调用类型转换方法。(DefaultTypeConverter的convertValue中的Object value参数是String[]类型的)

        * 继承StrutsTypeConverter

        * 覆盖convertFromString和convertToString

        范例:

         public class UtilDateConverter extends StrutsTypeConverter {

              * 好像只能解析action中带有setget方法的属性。

              private static final String PATTERN = "yyyy/MM/dd";

              //浏览器提交到服务器是调用,将字符串转换成对象

              @Override

              public Object convertFromString(Map context, String[] values, Class toClass) {

                           //获得页面传过来的字符串,可能有多个名字相同,所以取第一个。

                           String dateString = values[0];

                           SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);

                           Date date = null;

                           try {

                                  //字符串,转换成日期类型。

                                  date = sdf.parse(dateString);

                            } catch (ParseException e) {

                                  e.printStackTrace();

                            }

                            return date;

                  }

                 //服务器向浏览器输出时调用,将某种类型转换成字符串。o是要转换成字符串的对象。

                 @Override

                 public String convertToString(Map context, Object o) {

                             Date date = (Date)o;

                             return new SimpleDateFormat("yyyy年MM月dd日").format(date);

                 }

            }

    2. 注册类型转换器

        * 局部类型转换器,局部类型转换器只对当前Action起作用,需要提供如下配置文件:

           MyActionName-conversion.properties,MyActionName指需要使用转换器的Action名称。”-conversion.properties“固定字符串,不能修改。我们AddUserAction类型转换器的配置

           文件名称为:AddUserAction-conversion.properties,该配置文件必须和Action放到同一个 目录中,该配置文件的格式为:Action中的属性名称=转换器的完整路径,如:

           birthday=com.bjpowernode.struts2.UtilDateConverter

           也可以转换数组,同样需要有setget方法。

        * 全局类型转换器,全局类型转换器可以是所有的Action起作用(同Struts1的类型转换器),需要提供如下配置文件:xwork-conversion.properties(该名字固定),该配置文件需要放到src下,该

           配置文件的格式:需要转换的类型完整路径=转换器的完整路径,如:

           java.util.Date=com.bjpowernode.struts2.UtilDateConverter

           自定义类型也可以转换。

           补:请求页面:

                 出生日期:<input type="text" name="birthday"><br>

                 显示页面:<s:property value="birthday"/>  或      <s:text name="date"></s:text>

            如果全局类型转换器和局部类型转换器同时存在,局部优先

            采用标签读取属性get方法时可以调用转换器的convertToString。采用JSTL不会调用,显示的是默认格式的时间。           

            类型转换时,若发生异常,fieldError中会自动把异常加上,英文的。

    3. Struts2 的类型转换,对于 8 个原生数据类型以及 Date,String 等常见类型,Struts2 可以使用内建的类型转换器实现自动的转换;但对于自定义的对象类型来说,就需要我们自己指定类型转换的方式了。

    国际化的支持

    1. Locale是由国家和语言代码构成的。类Locale中有相应的处理国际化的方法。

    2. 国际化资源文件是由baseName+Locale.properties构成,放置在src下

        资源文件中的key名称要统一,value可以根据不同的语言而不同.

        basename+语言代码+国家代码 

    3. 国际化的内容

        * 在页面中的硬编码

        * 动态文本(提示或错误)

    4. 配置baseName

        <constant name="struts.custom.i18n.resources" value="Message"/> 

    5. 提供国际化资源文件

        * Message.properties               (basename)

        * Message_zh_CN.properties

        * Message_en_US.properties

    6. 包级别国际化格式固定:package_language_country.properties。如果操作不执行包中的类,那么包级别国际化无效   

    7. 类级别国际化:类名称_language_country.properties放到相应的包中。只要执行到类时国际化才生效

    8. 中英文日期格式不一样,输入时注意,看语言。

    9. 配置basename.propertie 为默认语言包,当没有符合规范的语言包是,找basename.propertie.

    10. 页面获取值用struts2标签,el获取不到值。

          eg

               <s:text name="ss"></s:text>

               <s:textfield  key="ss"></s:textfield>   (一个页面显示名字是ss值的文本域,自己试试)

  • 相关阅读:
    bzoj3505 数三角形 组合计数
    cogs2057 殉国 扩展欧几里得
    cogs333 荒岛野人 扩展欧几里得
    bzoj1123 BLO tarjan求点双连通分量
    poj3352 road construction tarjan求双连通分量
    cogs1804 联合权值 dp
    cogs2478 简单的最近公共祖先 树形dp
    cogs1493 递推关系 矩阵
    cogs2557 天天爱跑步 LCA
    hdu4738 Caocao's Bridge Tarjan求割边
  • 原文地址:https://www.cnblogs.com/doudouxiaoye/p/5693409.html
Copyright © 2011-2022 走看看