zoukankan      html  css  js  c++  java
  • java struts2入门学习---文件下载的二种方式

    一.关于文件下载:

    文件下载的核心思想即是将文件从一个地方拷贝到另一个地方.

    1.传统方式:

      在Action中加入大量servlet api 操作.优点是好理解,缺点是耦合度高。

    2.stream方式:

         使用struts2中的stream拦截器进行操作

    二.实例:

    我这里用的是maven,贴出pom.xml:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.amos</groupId>
        <artifactId>struts2_learn</artifactId>
        <packaging>war</packaging>
        <version>0.0.1-SNAPSHOT</version>
        <name>struts2_learn Maven Webapp</name>
        <url>http://maven.apache.org</url>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.struts</groupId>
                <artifactId>struts2-core</artifactId>
                <version>2.3.16</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-io</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>jstl</groupId>
                <artifactId>jstl</artifactId>
                <version>1.1.2</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>taglibs</groupId>
                <artifactId>standard</artifactId>
                <version>1.1.2</version>
            </dependency>
        </dependencies>
        <build>
            <finalName>struts2_learn</finalName>
        </build>
    </project>
    View Code

    1.使用传统方式实现文件下载:

    DownloadAction.java

    package download;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.struts2.ServletActionContext;
    import com.opensymphony.xwork2.ActionSupport;
    /** 
    * @ClassName: DownloadAction 
    * @Description: 文件下载
    * @author: amosli
    * @email:amosli@infomorrow.com
    * @date Feb 13, 2014 1:22:23 AM  
    */
    public class DownloadAction extends ActionSupport {
        private static final long serialVersionUID = -5609061774548242181L;
        private String fileName;//文件名称
        public void setFileName(String fileName) {
            if (ServletActionContext.getRequest().getMethod().equals("GET")) {
                try {
                    byte[] bytes = fileName.getBytes("ISO8859-1");//将get方式提交的中文进行处理,即将编码由ISO8859-1转为utf-8
                    fileName = new String(bytes, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            this.fileName = fileName;
        }
    
        // 下载
        public String execute() throws Exception {
            // 1.传统下载方式
            // 取得HttpServletResponse对象
            HttpServletResponse response = ServletActionContext.getResponse();
            // 取得ServletContext对象
            ServletContext context = ServletActionContext.getServletContext();
            // 通知浏览器以下载方式打开文件
            response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
            // 取得需要下载文件的根目录
            String realPath = context.getRealPath("/WEB-INF/download");
            // 构造子节输入流
            InputStream is = new FileInputStream(realPath + "/" + fileName);
            // 构造子节输出流
            OutputStream os = response.getOutputStream();
            byte[] b = new byte[1024];
            int len = 0;
            while ((len = is.read(b)) > 0) {
                os.write(b, 0, len);
            }
            is.close();
            os.close();
            return SUCCESS;
        }
    }

    download.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix="c" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        英文需要编码
        <a href="/struts2_learn/DownloadAction?fileName=building.jpg"
            style="text-decoration: none">
            building.jpg 
        </a> <hr>
        <%-- <c:url var="myURL" value="/DownloadAction">
            <c:param name="fileName" value="建筑.jpg" />
        </c:url>
        <a href="${myURL}" style="text-decoration: none"> 建筑.jpg </a> --%>
    </body>
    </html>

    download_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="download" extends="struts-default">
                <action name="DownloadAction" class="download.DownloadAction" method="execute">
                </action>
            </package>
    </struts>

    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>
        <!--<include file="config/upload.xml"></include> -->
        <!-- 加载其他配置文件 -->
        <!-- <include file="config/upload-interceptor.xml"></include> -->
        <!-- 加载属性文件-国际化 -->
        <!-- <constant name="struts.custom.i18n.resources" value="message"></constant> -->    <!-- 结果集 -->
        <!-- <include file="config/result_struts.xml"></include> -->
        <!-- 类型转换 -->
        <!-- <include file="config/type_struts.xml"></include> -->
        <!-- 文件下载 -->
        <include file="config/download_struts.xml"></include>
    </struts>

    效果如下图所示,点击building.jpg即可开始下载:

       

    代码运行顺序:

    首先,项目启动,加载struts.xml--->download_struts.xml-->将对应的DownloadAction加载.

    其次,用户访问download.jsp页面,点击超链接,即开始调用DownloadAction进行下载.

    核心程序即为DownloadAction.java,将要下载的文件写入到输入流,FileInputStream,然后再将文件从输入流写入到输出流,即将文件从一个地方拷贝到另一个地方.HttpServletResponse,将文件回写给浏览器,以达到下载文件的目的.

    最后,文件成功下载,文件被拷贝到指定的地方.

    这里要注意的是如果是GET请求方式,那么要注意中文乱码的问题,这里涉及到转码的问题,要做一个判断,详情可参考上面的代码.

    2.使用stream方式进行文件下载:

    DownloadStreamAction.java

    package download;
    import java.io.InputStream;
    import java.net.URLEncoder;
    import org.apache.struts2.ServletActionContext;
    import com.opensymphony.xwork2.ActionSupport;
    /** 
    * @ClassName: DownloadStreamAction 
    * @Description: 现代下载方式
    * @author: amosli
    * @email:amosli@infomorrow.com
    * @date Feb 13, 2014 12:35:26 AM  
    */
    public class DownloadStreamAction extends ActionSupport {
        private static final long serialVersionUID = -2747191035343710583L;
        private String fileName;
        public void setFileName(String fileName) throws Exception {
            if(ServletActionContext.getRequest().getMethod().equals("GET")){
                byte[] bytes = fileName.getBytes("ISO8859-1");
                fileName=new String(bytes,"utf-8");
            }
            this.fileName = fileName;
        }
        public String getFileName() throws Exception {
            return URLEncoder.encode(fileName, "utf-8");
        }
        public InputStream getImageStream() throws Exception {
            InputStream inputStream = ServletActionContext.getServletContext().getResourceAsStream("/WEB-INF/download/"+fileName);
            return inputStream;
        }
    }

    download_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="download" extends="struts-default">
                <action name="DownloadAction" class="download.DownloadAction" method="execute">
                </action>
            </package> -->
            <package name="download" extends="struts-default">
                <action name="DownloadAction" class="download.DownloadStreamAction" method="execute">
                <!-- 以stream二进制流的方式打开 -->
                <result name="success" type="stream">
                    <!-- 指明文件的下载类型 -->
                    <param name="contentType">image/jpeg</param>    
                    <!-- 指明如果取得需要下载文件的InputStream输入流 -->
                    <param name="inputName">imageStream</param>    
                    <!-- 指明让浏览器以下载框的方式打开 -->
                    <param name="contentDisposition">attachment;filename="building.jpg"</param>    
                    <!--<param name="contentDisposition">attachment;filename=${fileName}</param>-->    
                    <!-- 指明下载文件时的字符数组byte[]大小 -->
                    <param name="bufferSize">1024</param>
                </result>
                </action>
            </package>
    </struts>

    这里如果仅仅看DownloadStreamAction,会发现代码简洁明了,少了很多,再看download_struts.xml,会发现之前我们自己做的事,都被struts代替了,比如字符数组的大小,这里以参数配置的形式出现,方便了许多.

    注意:imageStream要和DownloadStreamAction中的getImageStream相对应,不可写错.

    关于其具体实现可以查看org.apache.struts2.dispatcher.StreamResult源码,其对应参数,看过源码后就会发现其实下载和传统方式差不多,就是将其优化了不少.

    3.实现过程中出现的问题

    HTTP Status 500 - The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
    
    type Exception report
    
    message The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
    
    description The server encountered an internal error that prevented it from fulfilling this request.
    
    exception
    
    org.apache.jasper.JasperException: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
        org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:56)
        org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:445)
        org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:117)
        org.apache.jasper.compiler.TagLibraryInfoImpl.generateTLDLocation(TagLibraryInfoImpl.java:311)
        org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:152)
        org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:410)
        org.apache.jasper.compiler.Parser.parseDirective(Parser.java:475)
        org.apache.jasper.compiler.Parser.parseElements(Parser.java:1427)
        org.apache.jasper.compiler.Parser.parse(Parser.java:138)
        org.apache.jasper.compiler.ParserController.doParse(ParserController.java:242)
        org.apache.jasper.compiler.ParserController.parse(ParserController.java:102)
        org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:198)
        org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
        org.apache.jasper.compiler.Compiler.compile(Compiler.java:353)
        org.apache.jasper.compiler.Compiler.compile(Compiler.java:340)
        org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:646)
        org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:357)
        org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
        org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:96)
    
    note The full stack trace of the root cause is available in the Apache Tomcat/7.0.42 logs.

    如上所示异常,困扰了很久,网上答案各异,这里最终解决方案是在pom.xml中填加如下内容:

    <dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.1.2</version>
    <scope>provided</scope>
    </dependency>

    上面的提示是说缺少jstl的jar包,这里也可以手动将jar包引入.

    遇到的其它问题基本上只耐心查看提示,基本上都解决了,这里感觉细心真心重要.

    本文源码链接:文件下载 https://github.com/amosli/strut2_learn

  • 相关阅读:
    Java MD5机密算法的使用
    JavaWeb学习总结-12 JSTL标签语言
    HTML5学习总结-09 拖放和手机触屏事件
    HTML5学习总结-08 应用缓存(Application Cache)
    HTML5学习总结-08 WebSocket 服务器推送
    软件架构阅读笔记06
    软件架构阅读笔记05
    软件架构阅读笔记04
    软件架构阅读笔记03
    软件架构阅读笔记02
  • 原文地址:https://www.cnblogs.com/amosli/p/3547414.html
Copyright © 2011-2022 走看看