Struts2学习笔记 | 关于文件的上传与下载

文件上传前表单做的准备

这个在之前学习JSP的时候有接触到,这里再次说明一次。

  • 需要把HTML表单的enctype属性设置为multipart/form-data

  • 需要把HTML表单的method属性设置为post

  • 需要添加<input type="file">字段

文件上传

  • Struts2的文件上传实际上使用的是commons FileUpload组件,所以要检查是否有commons-fileupload-1.4.jarcommons-io-2.6.jar这两个jar包。

  • Struts2进行文件上传需要使用FileUpload拦截器

  • 在Action类中定义三个属性并提供对于的gettersetter方法
    文件的File对象:File [fileFieldName]
    文件类型:String [fileFieldName]ContentType
    文件名:String [fileFieldName]FileName
    有了这三个属性就可以得到文件的基本信息了

  • 使用IO流进行文件的上传

Demo如下:
UploadAction文件:

package com.cerr.struts2.upload;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;

import javax.servlet.ServletContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class UploadAction extends ActionSupport {
    private File ppt;
    private String pptContentType;
    private String pptFileName;
    private String pptDesc;

    public String getPptDesc() {
        return pptDesc;
    }

    public void setPptDesc(String pptDesc) {
        this.pptDesc = pptDesc;
    }

    public File getPpt() {
        return ppt;
    }

    public void setPpt(File ppt) {
        this.ppt = ppt;
    }

    public String getPptContentType() {
        return pptContentType;
    }

    public void setPptContentType(String pptContentType) {
        this.pptContentType = pptContentType;
    }

    public String getPptFileName() {
        return pptFileName;
    }

    public void setPptFileName(String pptFileName) {
        this.pptFileName = pptFileName;
    }

    @Override
    public String execute() throws Exception {
        System.out.println(ppt);
        System.out.println(pptContentType);
        System.out.println(pptFileName);
        System.out.println(pptDesc);
        ServletContext servletContext = ServletActionContext.getServletContext();
        String dir = servletContext.getRealPath("/files/"+pptFileName);

        //接下来就io操作
        FileOutputStream outputStream = new FileOutputStream(dir);
        FileInputStream inputStream = new FileInputStream(ppt);
        byte [] buffer = new byte[1024];
        int len = 0;
        while((len = inputStream.read(buffer))!= -1){
            outputStream.write(buffer,0,len);
        }
        outputStream.close();
        inputStream.close();
        return super.execute();
    }
}

一次上传多个文件

若传递多个文件,则上述提到的三个属性改为List类型并更新其gettersetter方法即可,示例:

private List<File> ppt;
private List<String> pptContentType;
private List<String> pptFileName;
private List<String> pptDesc;

返回的是对应的集合
如果上面的Demo要改成上传多个文件,则只需要把对一个对象的操作改成对一个集合对象的操作即可。

对上传进行限制

  • 可以通过配置FileUploadInterceptor拦截器的参数的方式来进行限制
    maximumSize:上传的单个文件的最大值,以字节为单位,默认的最大值为2M
    allowedTypes:允许的上传文件的类型,多个类型之间使用逗号分割
    allowedExtensions:允许的上传文件的扩展名,多个扩展名之间使用逗号分割

  • org.apache.struts2下的default.properties文件中有对上传的文件总的大小的限制,名字为struts.multipart.maxSize,可以使用常量的方式来修改该限制。上传的总的大小要注意不能超过该值,在上传多个文件的时候即使单个满足,但是总量超了的话,也会出现错误,不过不会自动打印出来,该错误存在actionError中,因此可以使用<s:actionerror />标签来打印。

  • 对于限制条件,可以在国际化资源文件中定义出错时的错误消息
    struts.messages.error.uploading:文件上传出错的消息
    struts.messages.error.file.too.large:文件超过最大值的消息
    struts.messages.error.content.type.not.allowed:文件内容类型不合法的消息
    struts.messages.error.file.extension.not.allowed:文件扩展名不合法的消息

对上述的例子进行修改,添加限制
首先在struts.xml文件中定义中配置修改拦截器

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
    <!-- 配置国际化资源文件 -->
    <constant name="struts.custom.i18n.resources" value="i18n"></constant>

    <package name="default" namespace="/" extends="struts-default">
        <!--自定义拦截器 -->
        <interceptors>
            <interceptor-stack name="cerrStack">
                <interceptor-ref name="defaultStack">
                    <param name="fileUpload.maximumSize">2000</param>
                    <param name="fileUpload.allowedTypes">text/html,text/xml</param>
                    <param name="fileUpload.allowedExtensions">html,dtd,xml</param>
                </interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 设置我们修改的该拦截器为默认的拦截器 -->
        <default-interceptor-ref name="cerrStack"></default-interceptor-ref>


        <action name="testUpload" class="com.cerr.struts2.upload.UploadAction">
            <result>/success.jsp</result>
            <result name="input">/upload.jsp</result>
        </action>
    </package>
</struts>

然后在国际化资源文件i18n.properties中定制错误消息

struts.messages.error.uploading=\u6587\u4ef6\u4e0a\u4f20\u51fa\u9519\u7684\u6d88\u606f
struts.messages.error.file.too.large=\u6587\u4ef6\u8d85\u8fc7\u6700\u5927\u503c\u7684\u6d88\u606f
struts.messages.error.content.type.not.allowed=\u6587\u4ef6\u5185\u5bb9\u7c7b\u578b\u4e0d\u5408\u6cd5\u7684\u6d88\u606f
struts.messages.error.file.extension.not.allowed=\u6587\u4ef6\u6269\u5c55\u540d\u4e0d\u5408\u6cd5\u7684\u6d88\u606f

这样就在上面代码的基础上添加了上传文件限制的功能了。
但是这样的话,实际上定制的消息并不完善,若要修改定制信息,则可以参考org.apache.struts2下的struts-messages.properties文件。


文件下载

  • Struts2中使用type="stream"的result进行下载即可。

  • 可以为streamresult设定如下参数
    contentType:结果类型
    contentLength:下载文件的长度
    contentDisposition:设定Content-Disposition响应头,该响应头指定响应是一个文件下载类型,一般取值为attachment;filename=文件名
    inputName:指定文件输入流的getter定义的那个属性的名字,默认为inputStream
    bufferSize:缓存的大小,默认为1024
    allowCaching:是否允许使用缓存
    contentCharSet:指定下载的字符集

  • 以上参数可以在Action中以getter方法的方式提供。
    配置文件:

<action name="testDownload" class="com.cerr.struts2.upload.DownLoadAction">
            <result type="stream">
                <param name="bufferSize">2048</param>
            </result>
</action>

例子:

package com.cerr.struts2.upload;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;

import javax.servlet.ServletContext;
import java.io.FileInputStream;
import java.io.InputStream;

public class DownLoadAction extends ActionSupport {
    private String contentType;
    private long contentLength;
    private String contentDisposition;
    private InputStream inputStream;

    public String getContentType() {
        return contentType;
    }

    public long getContentLength() {
        return contentLength;
    }

    public String getContentDisposition() {
        return contentDisposition;
    }

    public InputStream getInputStream() {
        return inputStream;
    }

    @Override
    public String execute() throws Exception {
        //确定各个成员变量的值
        contentType="text/html";
        contentDisposition="attachment;filename=aa.png";
        ServletContext servletContext = ServletActionContext.getServletContext();
        String fileName = null;
        fileName = servletContext.getRealPath("/files/1.png");
        System.out.println(fileName);
        inputStream = new FileInputStream(fileName);
        contentLength = inputStream.available();
        return super.execute();
    }
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容