前面我们刚刚学完文件上传,那么我们就接着来看和文件上传相对应的文件下载吧。对于文件上传而言,文件下载实现起来要简单的多。通常我们可以直接将一个超链接的地址指向我们想要给用户下载的资源即可。但是如果这些资源是浏览器能够解析的文件类型,比如html文件等,那么浏览器将不会提示用户下载这些文件了,而是会直接在浏览器中打开。这样做还有一个问题,那就是我们的资源文件的地址就直接暴露给用户了,它可以在其他的页面中被轻易的引用,这往往让我们觉得不太安全。那么就需要通过某种手段来告诉浏览器,让它提示用户下载我们的资源文件,并且将这些资源文件的真实地址隐藏起来。
使用Jsp/Servlet实现文件下载
首先我们使用Jsp和Servlet来完成我们上面手的文件下载功能。
public class FileDownServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
File file = new File(getServletContext().getRealPath("/down")
+ "/AdobeReader8.rar");
FileInputStream in = new FileInputStream(file);
OutputStream out = resp.getOutputStream();
resp.setContentType("Application/Octet-stream;charset=utf-8");
resp.addHeader("Content-Disposition",
"attachment; filename="+file.getName());
resp.addHeader("Content-Length::", file.length() + "");
byte[] b = new byte[1024];
int len = 0;
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
out.close();
in.close();
}
}
Input.jsp
<body>
<ahref="FileDownServlet">点击下载</a>
</body>
测试(打开浏览器,点击链接):
可以看到,这样一来,即使是文本文件,也可以提供给用户下载,并且很好的隐藏了文件资源的真实地址。因为文件的真实地址是我们在文件中通过某种方式获得的,并且是以流的形式输出到浏览器,那么浏览器看到的就只有当前jsp文件的地址。我们可以通过在链接上传一些参数(比如文件的id号),然后在Servlet中通过该Id号到数据库中去查询文件的真实的值和名字,也可通过算法直接算出真实地址。
这样虽然可以对文件进行下载了,但是它不支持断点续传功能,即下载的过程不能中断,一旦中断就需要重新下载了。
支持断点续传
实现断点续传的基本原理就是在请求头中加上一个Range参数,这个参数告诉流从什么地方开始下载,如果Rang参数为空或者0那么表示从头开始下载,如果参数有值,表示从流中跳过这么多字节再下载。如果服务端查询到是从头开始下载,那么就应该将响应头状态设置为200,如果是续传,那么应该将响应头设置为206.然后设置头参数Accept-Ranges的值为bytes,说明以字节流的方式传输,是下载文件。接着设置响应字节跳转值,Content-Range属性的值 这个值的格式为 "请求参数Range-流总长度减去1/流总长度"
最后开始向客户端传输响应流,这个流用OutputStream.skip(intp)方法跳过请求参数Range数值进行传输。我们将上面的例子改为支持断点续的服务端:
public class FileDownServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
File file = new File(getServletContext().getRealPath("/down")
+ "/Access2003.exe");
if (file.exists()) {
long p = 0;
long fileLength;
fileLength = file.length();
InputStream in = new FileInputStream(file);
response.reset();
response.setHeader("Accept-Ranges", "bytes");
// 查看是否头信息中包含Range参数
if (request.getHeader("Range") != null) {
// 设置相应头状态(206)
response
.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);
// 通过头信息获取Range参数的(整数)值
p = Long.parseLong(request.getHeader("Range").replaceAll(
"bytes=", "").replaceAll("-", ""));
}
response.setHeader("Content-Length", new Long(fileLength - p)
.toString());
if (p != 0) {
// 断点开始
// 响应的格式是:
// Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]
String contentRange = new StringBuffer("bytes ").append(
new Long(p).toString()).append("-").append(
new Long(fileLength - 1).toString()).append("/")
.append(new Long(fileLength).toString()).toString();
response.setHeader("Content-Range", contentRange);
// 跳过指定数量的字节
in.skip(p);
}
response.addHeader("Content-Disposition", "attachment;filename="
+ file.getName());
byte[] buf = new byte[1024];
int len = 0;
// 开始写入数据
while ((len = in.read(buf)) != -1) {
response.getOutputStream().write(buf, 0, len);
response.getOutputStream().flush();
}
in.close();
}
}
Input.jsp页面保持不变。
测试(下载工具需要支持断点续传,这里我使用快车):
通过从上面的两张图中可以看出,从头下载和续传下载在请求头上的区别。
使用Struts2实现文件下载
Struts2中提供了一种叫做stream的结果类型,通过它可以直接将一个InputStream传送给它,它就会自动的提供给客户端下载。原来一些我们在程序中使用代码设置的头信息,现在可以在Action的配置文件中配置了(当然也可以通过代码设置)。下面我们就动手做一个实例吧:
public class DownAction extends ActionSupport implements ServletContextAware {
private int id;
private InputStream inputStream;
private ServletContext context;
private String fileName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public InputStream getInputStream() {
fileName = id + ".exe";
return context.getResourceAsStream("/down/" + id + ".exe");
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
public void setServletContext(ServletContext context) {
this.context = context;
}
}
down.jsp
<body>
<ahref="down.action?id=1">下载地址1</a><br/>
<ahref="down.action?id=2">下载地址2</a>
</body>
struts.xml
<actionname="down"class="action.DownAction">
<resultname="success"type="stream">
<paramname="contentType">application/octet-stream</param>
<paramname="contentDisposition">filename=${fileName}</param>
</result>
</action>
测试:
配置文件中这些关于响应参数的设置也可以通过StreamRsult类提供的方法来设置。
Struts2文件下载要实现断点续传,思路和我们前面使用jsp/servlet实现断点断点续传的思路相同。主要就是请求头参数和响应头参数的处理。断点续传的时候,下载位置由客户端来提供的,那么我们在服务器端只要具有能够根据客户端请求参数来移动输入流指针位置的功能,就能够实现断点续传。当然,上面只是我自己一些理解和看法,如有错误还希望路过的老鸟指正,感激不尽!
分享到:
相关推荐
根据给定的文件信息,以下是对Struts2学习笔记中涉及的关键知识点的详细解析: ### Struts2框架概览 #### MVC模式的理解与演进 Struts2是基于MVC(Model-View-Controller)模式设计的一种Java Web开发框架。在MVC...
Struts2支持多种结果类型,如dispatcher(默认,转发到JSP)、stream(下载文件)等。 五、OGNL(Object-Graph Navigation Language) OGNL是Struts2的表达式语言,用于在Action和视图之间传递数据。它能直接访问...
在实际项目中,Struts2可以处理类型转换、文件上传下载、拦截器(Interceptor)防止重复提交等问题。Interceptor是Struts2中的重要特性,它允许在Action执行前后插入额外的处理逻辑,如登录验证、日志记录等。深入...
### Struts2 学习重点知识点总结 #### 一、Struts2 概念与架构 **1.1 Struts2 简介** - **定义**:Struts2 是 Apache 组织提供的一个基于 MVC 架构模式的开源 Web 应用框架。 - **核心**:Struts2 的核心其实是 ...
### Struts2学习笔记知识点详解 #### 一、Struts2框架的基本引入步骤 ##### 1. 导入Struts2相关Jar包 在引入Struts2框架时,首先需要将Struts2的相关Jar包导入到项目的类路径中。这些Jar包通常包括核心库以及其他...
### Struts2学习笔记之文件上传与Ajax开发 #### Struts2文件上传 **文件上传简介** 文件上传是Web应用中常见的功能之一,Struts2框架内置了对文件上传的支持,使得开发者能够轻松地实现这一功能。为了确保文件...
### Struts2学习笔记知识点概览 #### 一、环境搭建 **1.1 Struts2简介** - **Struts2概述**:Struts2是一个开源的MVC框架,它结合了Struts 1.x、WebWork和其他一些框架的优点。Struts2的主要目标是简化Web应用程序...
笔记中可能详细讲解了Struts2的配置文件,如struts.xml,它是整个应用的配置中心,定义了Action的映射、结果类型、拦截器栈等。在Action配置中,我们可以指定Action类、方法以及对应的URL路径,实现请求与业务的关联...
3. **使用Struts2进行下载**:通过设置Action的结果类型为`stream`,并提供文件流,Struts2可以生成下载链接。 **六.Struts2的属性驱动和模型驱动** 1. **属性驱动**:Action类中的字段直接对应请求参数,Struts2...
5. **结果类型(Result Types)**:Struts2支持多种结果类型,如dispatcher(转发到JSP页面),stream(下载文件),redirect(重定向)等,可以根据不同需求选择合适的结果类型。 6. **OGNL(Object-Graph ...
struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换
在这个“Struts2实现文件下载功能”的示例中,我们将深入探讨如何利用Struts2框架来实现在web应用中让用户下载文件的功能。 首先,我们需要理解文件下载的基本原理。在Web应用中,当用户点击一个链接或提交一个表单...
在Struts2中处理文件下载是常见的需求,比如用户请求下载服务器上的文件,如PDF、图片或其他类型的文档。本案例"Struts2之struts012"将深入探讨如何在Struts2中实现文件下载的功能。 首先,我们需要创建一个Action...
标签在Struts2配置文件中起到了划分和组织Action的作用,类似于Java中的包(package)。它允许我们将具有相同功能或关联的Action归类在一起,解决Action命名冲突的问题。例如,我们可以为前端和后端分别创建名为...
本篇文章将详细探讨如何在Struts2框架下实现文件的上传与下载。 首先,我们需要了解Struts2中的文件上传机制。Struts2提供了`FileUploadInterceptor`拦截器来处理文件上传请求。在处理文件上传时,开发者需要在...
在本篇“Struts2学习笔记十四”中,我们将深入探讨Struts2框架如何实现文件上传和下载功能,这是web应用中常见的需求,尤其在处理用户提交的表单数据时。我们将不涉及具体代码,而是重点讲解相关概念和技术原理。 ...
在本篇“Struts2学习笔记十三”中,我们将深入探讨Struts2如何处理文件上传和下载,这是Web开发中常见的需求。 文件上传在Web应用中广泛用于让用户提交图片、文档或其他类型的数据。Struts2提供了一个名为`...