一.关于文件下载:
文件下载的核心思想即是将文件从一个地方拷贝到另一个地方.
1.传统方式:
在Action中加入大量servlet api 操作.优点是好理解,缺点是耦合度高。
2.stream方式:
使用struts2中的stream拦截器进行操作
二.实例:
我这里用的是maven,贴出pom.xml:
4.0.0
com.amos
struts2_learn
war
0.0.1-SNAPSHOT
struts2_learn Maven Webapp
http://maven.apache.org
junit
junit
4.11
test
org.apache.struts
struts2-core
2.3.16
org.apache.commons
commons-io
1.3.2
jstl
jstl
1.1.2
provided
taglibs
standard
1.1.2
struts2_learn
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
Insert title here building.jpg建筑.jpg --%>
download_struts.xml
/p>
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
struts.xml
/p>
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
效果如下图所示,点击building.jpg即可开始下载:
代码运行顺序:
首先,项目启动,加载struts.xml--->download_struts.xml-->将对应的DownloadAction加载.
其次,用户访问download.jsp页面,点击超链接,即开始调用DownloadAction进行下载.
核心程序即为DownloadAction.java,将要下载的文件写入到输入流,FileInputStream,然后再将文件从输入流写入到输出流,即将文件从一个地方拷贝到另一个地方.HttpServletResponse,将文件回写给浏览器,以达到下载文件的目的.
最后,文件成功下载,文件被拷贝到指定的地方.
这里要注意的是如果是GET请求方式,那么要注意中文乱码的问题,这里涉及到转码的问题,要做一个判断,详情可参考上面的代码.
2.使用stream方式进行文件下载:
DownloadStreamAction.java
packagedownload;importjava.io.InputStream;importjava.net.URLEncoder;importorg.apache.struts2.ServletActionContext;importcom.opensymphony.xwork2.ActionSupport;/*** @ClassName: DownloadStreamAction
* @Description: 现代下载方式
*@author: amosli
* @email:amosli@infomorrow.com
* @date Feb 13, 2014 12:35:26 AM*/
public class DownloadStreamAction extendsActionSupport {private static final long serialVersionUID = -2747191035343710583L;privateString fileName;public void setFileName(String fileName) throwsException {if(ServletActionContext.getRequest().getMethod().equals("GET")){byte[] bytes = fileName.getBytes("ISO8859-1");
fileName=new String(bytes,"utf-8");
}this.fileName =fileName;
}public String getFileName() throwsException {return URLEncoder.encode(fileName, "utf-8");
}public InputStream getImageStream() throwsException {
InputStream inputStream= ServletActionContext.getServletContext().getResourceAsStream("/WEB-INF/download/"+fileName);returninputStream;
}
}
download_struts.xml
/p>
"http://struts.apache.org/dtds/struts-2.3.dtd">
image/jpeg
imageStream
attachment;filename="building.jpg"
1024
这里如果仅仅看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 fulfillingthisrequest.
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.(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中填加如下内容:
jstl
jstl
1.1.2
provided
上面的提示是说缺少jstl的jar包,这里也可以手动将jar包引入.
遇到的其它问题基本上只耐心查看提示,基本上都解决了,这里感觉细心真心重要.