通过Servlet实现文件的下载
2013-04-22 18:11
399 查看
当我们实现一个文件下载功能时,大多数人是通过Strust等框架实现的。Strust框架把底层的文件下载细节隐藏了起来,使我们不得其要领。下面我通过一个程序示例来再现通过Servlet下载文件的细节和原理。
程序源码
web.xml
DownloadServlet.java
解释:
1、contentType用于定义用户的浏览器如何显示将要加载的数据,或者如何处理将要加载的数据。如网页的contentType是text/html,jpeg图片的contentType是image/jpeg。如果不知道文件类型,可以设置为二进制流文件 application/octet-stream
2、contentType和fileRoot(待下载文件的目录)通过web.xml配置。
3、resp.setContentType()、resp.setContentLength()、resp.addHeader("Content-Disposition", "attachment; filename=" + fileName); 三个调用设置一些必要的响应报头(reponse header)。
运行结果:
1、浏览器地址栏输入:http://localhost:8080/test/download?fileName=test.mkv 回车(文件“d:/test.mkv”的大小为700M)
2、浏览器弹出下载提示窗口,但未点击保存。控制台先打印几条日志,然后停滞,说明已经向输出流写入了4kB左右(程序中byte数组的大小为4096B)的数据了。
3、选择保存位置后,点击保存。此时控制台开始疯狂地输出log。。。
4、最后下载完成,此次Request结束。
小结:
文件下载的原理非常简单,就是把数据从一个输入流中读出数据,再写入一个输出流。这里的输入流是FileInputStream(为了提高速度,对其包装了一个装饰类BufferedInputStream,以提供缓冲功能),输出流是ServletOutputStream。
源码中的定义,public abstract class ServletOutputStream extends OutputStream。说明ServletOutputStream继承了OutputStream,它和FileOutputStream等输出流是一样的。
程序源码
web.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <!--可以配置一些Listener 或 Filter 来观察一些对象的生命周期 --> <servlet> <servlet-name>download_servlet</servlet-name> <servlet-class>edu.shao.webapp.sample.DownloadServlet</servlet-class> <init-param> <param-name>fileRoot</param-name> <param-value>d:/</param-value> </init-param> <init-param> <param-name>contentType</param-name> <param-value>application/octet-stream</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>download_servlet</servlet-name> <url-pattern>/download</url-pattern> </servlet-mapping> </web-app>
DownloadServlet.java
package edu.shao.webapp.sample; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URLEncoder; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class DownloadServlet extends HttpServlet{ private static final long serialVersionUID = 1L; public static Logger logger=LogManager.getLogger(DownloadServlet.class); private String contentType; private String enc="UTF-8"; private String fileRoot; @Override public void init(ServletConfig config) throws ServletException { contentType = config.getInitParameter("contentType"); fileRoot = config.getInitParameter("fileRoot"); } @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { logger.debug("Do Get Method."); String fileName=req.getParameter("fileName"); String filePath=fileRoot+File.separator+fileName; File downloadFile=new File(filePath); if (downloadFile.exists()) { logger.info("File exist"); resp.setContentType(contentType); Long length=downloadFile.length(); resp.setContentLength(length.intValue()); fileName = URLEncoder.encode(downloadFile.getName(), enc); resp.addHeader("Content-Disposition", "attachment; filename=" + fileName); ServletOutputStream servletOutputStream=resp.getOutputStream(); FileInputStream fileInputStream=new FileInputStream(downloadFile); BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream); int size=0; byte[] b=new byte[4096]; while ((size=bufferedInputStream.read(b))!=-1) { logger.info("write to output stream.."); servletOutputStream.write(b, 0, size); } servletOutputStream.flush(); servletOutputStream.close(); bufferedInputStream.close(); }else { logger.info("File is not exist"); } } }
解释:
1、contentType用于定义用户的浏览器如何显示将要加载的数据,或者如何处理将要加载的数据。如网页的contentType是text/html,jpeg图片的contentType是image/jpeg。如果不知道文件类型,可以设置为二进制流文件 application/octet-stream
2、contentType和fileRoot(待下载文件的目录)通过web.xml配置。
3、resp.setContentType()、resp.setContentLength()、resp.addHeader("Content-Disposition", "attachment; filename=" + fileName); 三个调用设置一些必要的响应报头(reponse header)。
运行结果:
1、浏览器地址栏输入:http://localhost:8080/test/download?fileName=test.mkv 回车(文件“d:/test.mkv”的大小为700M)
2、浏览器弹出下载提示窗口,但未点击保存。控制台先打印几条日志,然后停滞,说明已经向输出流写入了4kB左右(程序中byte数组的大小为4096B)的数据了。
3、选择保存位置后,点击保存。此时控制台开始疯狂地输出log。。。
4、最后下载完成,此次Request结束。
小结:
文件下载的原理非常简单,就是把数据从一个输入流中读出数据,再写入一个输出流。这里的输入流是FileInputStream(为了提高速度,对其包装了一个装饰类BufferedInputStream,以提供缓冲功能),输出流是ServletOutputStream。
源码中的定义,public abstract class ServletOutputStream extends OutputStream。说明ServletOutputStream继承了OutputStream,它和FileOutputStream等输出流是一样的。
相关文章推荐
- java中通过Servlet实现文件下载
- Servlet和Jsp实现原生的上传与下载文件
- Servlet实现文件下载
- Servlet实现文件下载
- php如何通过header文件头实现文件下载
- 通过NSURLSessionDownloadTask代理实现下载大文件
- C# WinForm通过WebClient实现文件上传下载
- 通过<iframe>,实现图片(文件)的上传以及文件(附件)的下载
- 通过okHttpUtils实现文件的上传下载
- 如何使 FlashGet "正常合法" 下载 Session 中的自定义文件链接呢? JSP/Servlet 实现!
- 利用Tomcat内置的servlet实现文件下载功能
- 通过设置http的头信息实现服务器不保存文件直接下载
- Jsp/Servlet:实现文件上传与下载
- java文件下载通过response流实现文件存储在客户端指定路径
- 使用Servlet实现文件下载的时候,避免浏览器自动打开文件
- 文件下载 Servlet实现
- Servlet实现文件下载
- jsp实现Servlet文件下载的方法
- java通过文件流实现下载文件
- servlet简单实现文件下载的方法