• Struts2之文件上传与下载


    时间:2017-1-11 15:47

    ——使用commons-fileupload组件上传

    1、客户端
        *   method="post"
        *   <input type="file" name="xx" />
        *   encType="multipart/form-data"

    2、服务器端
        使用commons-fileupload。
        *   DiskFileItemFactory
        *   ServletFileUpload
        *   FileItem

    ——Struts2文件上传

    默认情况下,Struts2框架使用commons-fileupload组件进行上传操作,所以需要导入commons-fileupload.jar。

    Struts2使用了一个interceptor帮助我们完成文件上传操作:
        <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>

    实现文件上传操作:

        页面中:

            <form action="${pageContext.request.contextPath }/upload" method="post" enctype="multipart/form-data">
                <input type="file" name="file" />
                <input type="submit" value="上传" />
            </form>

            如果要同时上传多个文件,那么所有"file"的name属性值必须相同。 


        Action中:
            public class UploadAction extends ActionSupport {

                /*
                 * 在Action类中需要声明三个属性
                 */
                private File file; // 上传文件,名称必须与表单页面中的name值相同
                private String fileContentType; // 上传文件类型,名称格式:name + ContentType
                private String fileFileName; // 上传文件名,名称格式:name + FileName
     
                /*
                 * 在FileUploadInterceptor中有如下三行代码,所以起名必须要规范
                 * String inputName = (String) fileParameterNames.nextElement();
                 * String contentTypeName = inputName + "ContentType";
                 * String fileNameName = inputName + "FileName";
                 */
                @Override
                public String execute() throws Exception {
                    System.out.println("上传文件的类型:" + fileContentType);
                    System.out.println("上传文件的名称:" + fileFileName);
     
     
                    // 完成文件上传
                    // 使用FileUtils的copyFile()方法将文件的输入流输出到指定位置
                    FileUtils.copyFile(file, new File("f:/upload", fileFileName));
     
                    return NONE;
                }
                public File getFile() {
                    return file;
                }
                public void setFile(File file) {
                    this.file = file;
                }
                public String getFileContentType() {
                    return fileContentType;
                }
                public void setFileContentType(String fileContentType) {
                    this.fileContentType = fileContentType;
                }
                public String getFileFileName() {
                    return fileFileName;
                }
                public void setFileFileName(String fileFileName) {
                    this.fileFileName = fileFileName;
                }
            }



    ——Struts2中文件上传细节

    1、控制上传文件大小
        在default.properties文件中定义了上传文件的大小:
            struts.multipart.maxSize=2097152 上传文件大小默认2M
        超出文件大小时,跳转到input视图,通过<s:actionerror />显示错误信息。

        可以在struts.xml文件中重新定义常量来修改上传文件大小限制。

        <constant name="struts.multipart.maxSize" value="86170804"/>
     


    2、修改显示错误信息
        默认在页面中显示的错误信息是英文的,可以在Struts2核心包下的struts-message.properties文件中找到预定义上传错误信息,在国际化文件中通过覆盖对应key显示错误信息:

        // 上传错误:{0}

        struts.messages.error.uploading=Error uploading: {0}
        // 上传文件过大:{0} "{1}" "{2}" {3}
        struts.messages.error.file.too.large=The file is to large to be uploaded: {0} "{1}" "{2}" {3}
        // 上传文件不允许:{0} "{1}" "{2}" {3}
        struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}
        // 上传文件扩展名不允许:{0} "{1}" "{2}" {3}
        struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
     
        # dedicated messages used to handle various problems with file upload - check {@link     JakartaMultiPartRequest#parse(HttpServletRequest, String)}
        struts.messages.upload.error.SizeLimitExceededException=Request exceeded allowed size limit! Max size allowed is: {0} but request was: {1}!
        struts.messages.upload.error.IOException=Error uploading: {0}!


        {0}:<input type=“file” name=“uploadImage”>中name属性的值
        {1}:上传文件的真实名称
        {2}:上传文件保存到临时目录的名称
        {3}:上传文件的类型(对struts.messages.error.file.too.large是上传文件的大小)
     
     


    3、多文件上传时每个文件大小控制以及上传文件的扩展名限制

        多文件上传时,要将Action中的属性声明为List集合或者数组:
            private List<File> file;
            private List<String> fileContentType;
            private List<String> fileFileName;
        然后在excuete()方法中进行操作。

        怎样限制每一个上传文件的大小及其上传文件的类型?

        在FileUploadInterceptor中有如下代码:

            protected Long maximumSize;    // 表示每个上传文件的大小
            protected Set<String> allowedTypesSet = Collections.emptySet();    // 表示上传文件的类型
            protected Set<String> allowedExtensionsSet = Collections.emptySet();    // 表示上传文件的扩展名
     

           使用配置文件设置上传文件总大小,对所有上传form有效,如果只想对当前form进行设置,可以设置fileUplpad拦截器属性:
            *   maximumSize:上传文件的最大长度(以字节为单位),默认为2M。
            *   allowedTypes:允许上传的文件类型,各类型之间以逗号分隔。
            *   allowedExtendsions:允许上传文件扩展名,各扩展名之间以逗号分隔。

        例如:
            <action name="upload" class="com.wyc.action.UploadAction">

                <interceptor-ref name="defaultStack">
                    <!-- 对fileUpload下的allowedExtension属性赋值 --> 
                    <param name="fileUpload.allowedExtensions">txt,mp3,doc</param>
                </interceptor-ref>
                <result name="input">/upload.jsp</result>
            </action>

        如果针对fileUpload进行参数设置,当出错时,在页面通过<s:filedError />回显错误信息。      

    4、在Struts2中默认使用的是commons-fileupload进行文件上传
        在default.properties文件中:
            # struts.multipart.parser=cos
            # struts.multipart.parser=pell
            struts.multipart.parser=jakarta    // jakarta表示apache开源项目
        可以修改默认上传方式。

        如果使用pell、cos进行文件上传,必须导入其jar包。



    ——文件下载

    1、文件下载方式:
        超链接
        服务器编码,通过流向客户端写回。

        下载的要求
        两个头、一个流
            *   Content-Type:表示传递给客户端文件的MIME类型。
                >   通过文件名称调用ServletContext的getMimeType()方法得到MIME类型。
            *   Content-Disposition:
                >   它的默认值为inline,表示在浏览器窗口中打开(当打不开时会弹框)。
                >   attachment;filename=xxx:表示类型为附件,并在弹框的界面中显示下载的文件名。
            *   流:要下载的文件数据。
                >   自己new 一个输入流即可,然后通过IOUtils完成流的数据写入。

    2、Struts中的文件下载
        通过<result type="stream">来完成。

        指定stream结果类型 需要指定一个 inputName参数,该参数指定一个输入流,提供被下载文件的入口。

        在struts-default.xml文件中可以找到stream结果视图:
            <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>

        在StreamResult类中有三个属性:
            *   protected String contentType = "text/plain";    // 该属性用于设置下载文件的MIME类型
            *   protected String contentDisposition = "inline";    // 该属性用于设置进行下载操作以及下载文件的名称
            *   protected InputStream inputStream;    // 该属性用于读取要下载的文件

        其中contentType、contentDisposition、inputStream可以在struts.xml文件中进行配置:
            <action name="download" class="com.wyc.action.DownloadAction">
                <result type="stream">
                    <param name="contentType">text/plain</param>
                    <param name="contentDisposition">attachment;filename=a.txt</param>
                    <!-- ${inputStream}表示调用当前Action的getInputStream()方法,是ognl表达式,如果不设置,则默认"inputStream",可查看StreamResult源码 -->
                    <param name="inputStream">${inputStream}</param>
                </result>
            </action>

        inputStream可以在Action获得,在Action类中定义一个方法:
            public InputStream getInputStream() throw FileNotFound {
                FileInputStream fis = new FileInputStream("F;/upload/" + filename);
                return fis;
            }

        然后直接在execute()方法中return SUCCESS即可。


    3、文件乱码问题
        超链接下载的文件是中文名,会出现乱码情况,服务器会出错。

        解决方法:
            在getInputStream()方法中添加:
                filename = new String(filename.getBytes("iso-8859-1"), "utf-8");


    4、动态获取下载文件名和文件类型
        在struts.xml文件中使用ognl表达式动态获取。
            <result type="stream">
                <!-- 调用当前Action中的getContentType()方法,得到其返回值 -->
                <param name="contentType">${contentType}</param>
                <param name="contentDisposition">attachment;filename=${downloadFileName}</param>
                <!-- ${inputStream}表示调用当前Action的getInputStream()方法,如果不设置,则默认"inputStream",可查看StreamResult源码 -->
                <param name="inputStream"></param>
            </result>


    5、示例代码:

    =============================================================================

    DownloadAction:

    package com.wyc.action;
     
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.InputStream;
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.util.Base64;
     
    import org.apache.struts2.ServletActionContext;
     
    import sun.misc.BASE64Encoder;
     
    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.ActionSupport;
     
    public class DownloadAction extends ActionSupport {
     
        // 要下载文件的名称
        private String filename;
     
        public InputStream getInputStream() throws FileNotFoundException, UnsupportedEncodingException{
            filename = new String(filename.getBytes("iso-8859-1"), "utf-8");
     
            FileInputStream fis = new FileInputStream("f:/upload/" + filename);
            return fis;
        }
     
        // 获取下载文件MIME类型
        public String getContentType(){
            return ServletActionContext.getServletContext().getMimeType(filename);
        }
     
        /*
         * 获取下载文件名称
         * 解决浏览器差异问题
         */
        public String getDownloadFileName() throws UnsupportedEncodingException{
            String agent = ServletActionContext.getRequest().getHeader("User-Agent");
            if(agent.contains("MSIE")){
                // IE浏览器
                filename = URLEncoder.encode(filename, "utf-8");
            } else if (agent.contains("FireFox")) {
                // 火狐浏览器
                BASE64Encoder base64Encoder = new BASE64Encoder();
                filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
            } else {
                // 其他浏览器
                filename = URLEncoder.encode(filename, "utf-8");
            }
            return filename;
        }
     
        @Override
        public String execute() throws Exception {
            System.out.println("进行下载...");

            // 直接return SUCCESS即可。 
            return SUCCESS;
     
        }
     
        public String getFilename() {
            return filename;
        }
     
        public void setFilename(String filename) {
            this.filename = filename;
        }
    }
     
    ----------------------------------------------------------------------------------------------------------------------------

    struts.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
    <struts>
        <package name="default" namespace="/" extends="struts-default">
            <action name="download" class="com.wyc.action.DownloadAction">
     
                <result type="stream">
                    <!-- 调用当前Action中的getContentType()方法,得到其返回值 -->
                    <param name="contentType">${contentType}</param>
                    <param name="contentDisposition">attachment;filename=${downloadFileName}</param>
                    <!-- ${inputStream}表示调用当前Action的getInputStream()方法,如果不设置,则默认"inputStream",可查看StreamResult源码 -->
                    <param name="inputStream"></param>
                </result>
            </action>
        </package>
    </struts>
  • 相关阅读:
    IntelliJ IDEA Community Edition 14.1.4下使用 Apache-Subversion搭建代码管理环境
    Eclipse+SVN搭建开发环境
    查看分区表中分区详细信息
    asp.net mvc 后台怎么接受前端返回的array list dictionary
    jquery 操作select
    asp.net mvc4 System.Web.Optimization找不到引用
    asp.net mvc4 设置build项目时,编译view页面
    c# ConfigurationSection
    Array基本操作
    For,Function,Lazy
  • 原文地址:https://www.cnblogs.com/wwwwyc/p/6375428.html
Copyright © 2020-2023  润新知