Struts2之文件上传与下载
阅读原文时间:2023年07月09日阅读:2

时间:2017-1-11 15:47

——使用commons-fileupload组件上传

1、客户端
    *   method="post"
    *  
    *   encType="multipart/form-data"

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

——Struts2文件上传

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

Struts2使用了一个interceptor帮助我们完成文件上传操作:
    

实现文件上传操作:

    页面中:

        

            

            

        

        如果要同时上传多个文件,那么所有"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视图,通过显示错误信息。

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

    

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}:中name属性的值

    {1}:上传文件的真实名称

    {2}:上传文件保存到临时目录的名称

    {3}:上传文件的类型(对struts.messages.error.file.too.large是上传文件的大小)

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

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

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

    在FileUploadInterceptor中有如下代码:

        protected Long maximumSize;    // 表示每个上传文件的大小

        protected Set allowedTypesSet = Collections.emptySet();    // 表示上传文件的类型

        protected Set allowedExtensionsSet = Collections.emptySet();    // 表示上传文件的扩展名

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

    例如:
        

            
                 

                txt,mp3,doc

            

            /upload.jsp

        

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

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中的文件下载
    通过来完成。

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

    在struts-default.xml文件中可以找到stream结果视图:
        

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

    其中contentType、contentDisposition、inputStream可以在struts.xml文件中进行配置:

        

            

                text/plain

                attachment;filename=a.txt

                

                ${inputStream}

            

        

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表达式动态获取。

        

            

            ${contentType}

            attachment;filename=${downloadFileName}

            

            

        

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

http://struts.apache.org/dtds/struts-2.3.dtd">

    

        

            

                

                ${contentType}

                attachment;filename=${downloadFileName}