• 笔记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值的文本域,自己试试)

  • 相关阅读:
    ASP.NET动态生成控件
    WGCLOUD如何禁用指令下发功能
    C#基于NAudio工具对Wav音频文件剪切(限PCM格式)
    C#多线程与多任务
    我的JQuery插件 Confirmer
    我的JQuery插件 submenu
    关于jQuery在asp.net中使用ajax的探讨
    发布jQuery表单验证插件 JQuery.validator.js
    TreeView递归绑定地区列表
    Uploadify(JQuery上传插件)在asp.net中使用例子
  • 原文地址:https://www.cnblogs.com/doudouxiaoye/p/5693409.html
Copyright © 2020-2023  润新知