11、Struts2 的文件上传和下载

文件上传

  1. 表单准备

    • 要想使用 HTML 表单上传一个或多个文件
    • 须把 HTML 表单的 enctype 属性设置为 multipart/form-data
    • 须把 HTML 表单的method 属性设置为 post
    • 需添加 <input type=“file”> 字段.
  2. Struts 对文件上传的支持

    • 在 Struts 应用程序里, FileUpload 拦截器和 Jakarta Commons FileUpload 组件可以完成文件的上传.
    • 步骤:
      1. 在 Jsp 页面的文件上传表单里使用 file 标签. 如果需要一次上传多个文件, 就必须使用多个 file 标签, 但它们的名字必须是相同的
      2. 在 Action 中新添加 3 个和文件上传相关的属性. 这 3 个属性的名字必须是以下格式
        • 基本的文件的上传: 直接在 Action 中定义如下 3 个属性, 并提供对应的 getter 和 setter
        • [File Name] : 类型-File -被上传的文件。例如:data(fileName要求和文件表单项的name一致
        • [File Name]ContentType : 类型-String -上传文件的文件类型。例如:dataContentType(用来接收文件类型(MIME值)
        • [File Name]FileName : String -上传文件的文件名。例如:dataFileName (用来接收文件的名字
      3. 如果上传多个文件, 可以使用 List
        • 若传递多个文件, 则上述的 3 个属性, 可以改为 List 类型! 多个文件域的 name 属性值需要一致.
  3. 示例代码

<s:form action="testUpload" enctype="multipart/form-data">
   <s:textfield name="userName[0]" label="用户-1"></s:textfield>
    <s:file name="photos" label="照片"></s:file>
    <s:textfield name="userName[1]" label="用户-2"></s:textfield>
    <s:file name="photos" label="照片"></s:file>
    <s:textfield name="userName[2]" label="用户-3"></s:textfield>
    <s:file name="photos" label="照片"></s:file>
    <s:submit value="提交"></s:submit>
</s:form>
public class UploadAction  extends ActionSupport{

    @Setter@Getter
    private List<File> photos;
    @Setter@Getter
    private List<String> photosContentType;
    @Setter@Getter
    private List<String> photosFileName;
    @Setter@Getter
    private List<String> userName;

    public String testUpload() throws IOException {
        System.out.println("userName: "+userName);
        System.out.println("photos: "+photos);
        System.out.println("photosFileName: "+ photosFileName);
        System.out.println("photosContentType: "+photosContentType);

        // 将文件传到服务器根目录下upload文件下
        // 获取ServletContext
        ServletContext servletContext = ServletActionContext.getServletContext();
        //获取真实路径
        String realPath = servletContext.getRealPath("/upload");
        System.out.println(realPath);
        File uploadFile = new File(realPath);
        //判断路径是否存在
        if (!uploadFile.exists()){
            //不存在创建
            uploadFile.mkdir();
        }
        for (int i = 0; i < photos.size(); i++) {
            UUID uuid = UUID.randomUUID();
            FileUtils.copyFile(photos.get(i), new File(realPath + "/" + uuid + photosFileName.get(i)));
        }
        return SUCCESS;
    }
}
  1. 处理几个小问题?

    1. 文件名重名,一般可以在文件名的前面生成一个UUID作为前缀。
    2. 限制单个文件的大小
    3. 限制文件的类型
    4. 限制总文件的大小
  2. 在Struts2 中提供了 FileUpload 拦截器 可以给我们设置这些属性值

    • FileUpload 拦截器有 3 个属性可以设置.
      • maximumSize: 上传单个文件的最大长度(以字节为单位), 默认值为 2 MB
      • allowedTypes: 允许上传文件的类型, 各类型之间以逗号分隔
      • allowedExtensions: 允许上传文件扩展名, 各扩展名之间以逗号分隔
      • 可以在 struts.xml 文件中覆盖这 3 个属性
    • 注意: 在 org.apache.struts2 下的 default.properties 中有对上传的文件总的大小的限制. 可以使用常量的方式来修改该限制struts.multipart.maxSize=2097152
<constant name="struts.devMode" value="true"/>

 <!-- 在这修改总文件的的大小 -->
 <constant name="struts.multipart.maxSize" value="2097152"/>
 <package name="default" namespace="/" extends="struts-default">
    <interceptors>
        <interceptor-stack name="myInterceptor">
            <interceptor-ref name="defaultStack">
                <!-- 修改单个文件大小,Commons FileUpload 组件默认接受上传文件总的最大值为 2M -->
                <param name="fileUpload.maximumSize">57,408</param>
                <!-- 允许上传的文件类型 -->
                <param name="fileUpload.allowedTypes">image/pjpeg,image/gif</param>
                <!-- 允许上传文件的扩展名 -->
                <param name="fileUpload.allowedExtensions">jpg,gif</param>
            </interceptor-ref>
        </interceptor-stack>
    </interceptors>

    <default-interceptor-ref name="myInterceptor"></default-interceptor-ref>
    
    <action name="testUpload" class="org.pan.action.UploadAction" method="testUpload">
        <result name="success">/WEB-INF/views/success.jsp</result>
        <result name="input">/upload.jsp</result>
    </action>
</package>
  1. 上传文件相关的错误消息?
    1. 与文件上传有关的出错消息在 struts-messages.properties 文件里预定义.
    2. 可以在文件上传 Action 相对应的资源文件 或者 在 i18n_zh_CN.properties 国际化资源文件中重新定义错误消息
struts.messages.error.file.too.large=你传的文件太大了
struts.messages.error.content.type.not.allowed=文件类型错误
struts.messages.error.file.extension.not.allowed=扩展名错误
struts.messages.upload.error.SizeLimitExceededException=文件总大小超过上限

文件下载

  1. 在某些应用程序里, 可能需要动态地把一个文件发送到用户的浏览器中, 而这个文件的名字和存放位置在编程时是无法预知的

  2. Stream 结果类型

    • Struts 专门为文件下载提供了一种 Stream 结果类型. 在使用一个 Stream 结果时, 不必准备一个 JSP 页面.
    • Stream 结果类型可以设置如下参数:
      • contentType:被下载的文件的 MIME 类型。默认值为 text/plain
      • contentLength:被下载的文件的大小,以字节为单位
      • contentDisposition: 可以设置下载文件名的ContentDispositon 响应头,默认值为 inline,通常设置为如下格式:
        • attachment;filename="document.pdf".
      • inputName:Action 中提供的文件的输入流。默认值为 inputStream
      • bufferSize:文件下载时缓冲区的大小。默认值为 1024
      • allowCaching :文件下载时是否允许使用缓存。默认值为 true
      • contentCharSet:文件下载时的字符编码。
        • 以上参数可以在 Action 中以 getter 方法的方式提供!
    • Stream 结果类型的参数可以在 Action 以属性的方式覆盖
    • 具体使用细节参看 struts-2.3.15.3-all/struts-2.3.15.3/docs/WW/docs/stream-result.html
  3. 示例代码

<a href="testDownLoad">下载</a>
public class DownLoadAction extends ActionSupport{
    //通常以下这几个参数会在Action 中提供
    @Setter@Getter
    private String contentType;
    @Setter@Getter
    private long contentLength;
    @Setter@Getter
    private String contentDisposition;
    @Setter@Getter
    private InputStream inputStream;

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

推荐阅读更多精彩内容